4 ms·
Curious why you think CreateProcess is worse than fork/exec. Sure it takes about a dozen parameters but is that really the end of the world?!? It’s much much ea
by rand_flip_bit 4y ago
Curious why you think CreateProcess is worse than fork/exec. Sure it takes about a dozen parameters but is that really the end of the world?!? It’s much much easier to use correctly and doesn’t have nearly as many of the pitfalls as fork/exec. Especially in large processes with lots of memory allocated. I genuinely don’t understand why people dislike it so much.
- jborean93 4y agoMost of the complaints I've seen are about the number of args and the complexity of calling it vs something simple like fork. There are a lot of knobs to turn which you need to be explicit about. That's not even getting into the whole ProcThreadAttributeList and the myriad of options it exposes. In saying all that I do prefer the `CreateProcess*` APIs on Windows vs the POSIX ones but that might be because I understand the former better.
- rand_flip_bit 4y agoIt’s fair to say the initial surface area of the API is more complex (at first glance). However, fork/exec don’t really scale that well beyond toy examples you see in blogs or CS101. Thing is, if you are using fork/exec, you are likely also calling a few other functions for things like redirecting IO, dealing with exec failing (creating a pipe with O_CLOEXEC, and you need to remember to use _exit instead of exit (or anything else) if exec fails. Plus there is all the complexity of dealing with the child pid, signals, not accidentally creating a zombie, etc. Ohh not to mention that all the pages in the processes memory need to be marked copy-on-write when fork is called, only for that to be reversed when exec is called. I hope you don’t have dozens or hundreds of gigabytes allocated in a multithreaded program, that will cost you. Ohh and of course, you can’t call anything between fork and exec that isn’t signal safe, so you need to be really careful, especially in languages with implicit allocation or exceptions. Ohh bonus points for the fact that it’s ill-formed for multithreaded programs to call fork without exec since that can leave things like locks in inconsistent states. The way both APIs handle file inheritance is absolutely horrendous, especially since most libcs don’t set the necessary flags. posix_spawn doesn't solve this either, since posix_atfork can open more files in the child, and multithreaded programs can have a TOCTOU bug if another thread opens files between the call to posix_spawn_file_actions and posix_spawn. TBF Windows is actually worse in this regard, since it’s race condition is a little more subtle. Ironically the best to way manage all of this nonsense is to create a child process first thing in main (another binary), which isn’t multithreaded, closes almost all files (uses a whitelist of fds) upfront, and spawns processes on behalf of the parent when requested (IPC). Ideally you would write this in C, minimize usage of libc, and avoid allocating tons of memory.
- stevenhuang 4y ago> Ironically the best to way manage all of this nonsense is to create a child process first thing in main That's a sensible strategy. Do you know if this design pattern has a name, of creating this "clean" process image base for forks via ipc?
- cryptonector 4y agoI would call it a spawn server, based on the "open server" or "doas" pattern, where you have a process that creates children to setuid() (etc.) which then set a private IPC service that open()s files and sends back the open FD to the caller.
- robocat 4y agoTo add, two good links on issues to beware of with fork(): https://lwn.net/Articles/785430/ https://lwn.net/Articles/785430/ https://www.microsoft.com/en-us/research/uploads/prod/2019/04/fork-hotos19.pdf https://www.microsoft.com/en-us/research/uploads/prod/2019/0...
- cryptonector 4y agoI don't think CreateProcess() is worse than fork/exec, and I didn't even mention fork/exec. It's pretty natural that one should even jump to the conclusion that "dislike of CreateProcess()" -> "preference for fork/exec", but I'm a bit of a contrarian: I think fork() is awful: https://news.ycombinator.com/item?id=30502392 https://news.ycombinator.com/item?id=30502392 My specific complaint about CreateProcess() is everything to do with how the child process is bootstrapped and how arguments get passed (as a single string! that the child has to parse like it were a shell! gaaaa!!!).
- LgWoodenBadger 4y agoWhat else is there besides fork/exec?
- neutrono 4y agoOnly one I could think of is posix_spawn[0], although it has different constraints than fork()/exec()... [0]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html#tag_16_371 https://pubs.opengroup.org/onlinepubs/9699919799/functions/p...
- cryptonector 4y agovfork/exec. posix_spawn(). Yes, CreateProcess(), but with the specific things about it that suck fixed.
- rand_flip_bit 4y agoSee my other comment on posix_spawn. It has its own issues and TOCTOU bugs that prevent it from being an actual alternative.
- cryptonector 4y agoWhat, O_CLOEXEC? Well, yes, you really need to use the new syscalls that let you set O_CLOEXEC atomically on new FDs.