4 ms·
I wish posix_spawn were ubiquitous; it's a much better process-launching interface than fork: it's naturally race-free and amenable to use in multi-threaded pro
by quotemstr 12y ago
I wish posix_spawn were ubiquitous; it's a much better process-launching interface than fork: it's naturally race-free and amenable to use in multi-threaded programs, and unlike fork(2), it plays well with turning VM overcommit off. (If overcommit is off and a large process forks, the system must assume that every COW page could be made process-private and reserve that much memory. Ouch.)
- cperciva 12y agoEven if VM overcommit is enabled, you shouldn't be forking from large processes, because the necessary kernel VM manipulation will kill your performance.
- quotemstr 12y agoYep. For that problem, there's vfork.
- cperciva 12y agoWhich is great, albeit easy to use wrong; but it's not portable, unfortunately.
- quotemstr 12y agoIt's portable enough: Linux, Darwin, and the BSDs all support it. Darwin also supports posix_spawn natively. Even Cygwin supports it, although Cygwin's vfork is currently just an alias for fork.
- girvo 12y agoI seem to remember Cygwin having all sorts of weird problems with fork behaviour, but I'm no C programmer let alone doing stuff on Windows, so I might be remembering incorrectly
- FooBarWidget 12y agoUnfortunately, posix_spawn is woefully underpowered. I can't make the child process a session leader (setsid) or process group leader (setpgrp). I can't set a working directory. Etcetera.
- quotemstr 12y agoYeah --- but at least it's fairly obvious how to add platform-specific extensions that won't conflict with future standards.
- wiml 12y agoAnd extensions to let us specify failure-case or other behavior of those extensions, and so on. But at that point, we're already heading down the road of implementing a tiny DSL for "the program that posix_spawn() should run after creating the new process but before exec()ing the new executable". Why not simply write that code in the host language? You could specify a thunk of code to be sent to the new process and executed there. Oh, you'll also need to pass any data structures that code relies on--- pass a closure, not just a thunk. And garbage-collected references to any system objects that those data structures rely on. Congratulations, now you have fork()! If you squint a little, that's exactly what fork() provides you --- a closure and continuation.
- quotemstr 12y agoYes, you end up with a tiny DSL for specifying transformations to make to a child process: they key difference is that the kernel can execute this DSL much more efficiently than it can code written in the host language: fork closes over the entire world, and posix_spawn doesn't have to do that.
- gilgoomesh 12y agoThe role of posix_spawn is for spawning "helper processes", not starting new process groups. This should overwhelming be your common launch case. posix_spawn is so much faster (on BSD/Mac anyway) that fork should be outright avoided. Processes requiring other permissions can/should be spawned by asking systemd/chron/init/launchd to launch them for you.