4 ms·
It's worth noting that on Linux, the address space itself is copy-on-write, but the page tables describing the address space are nevertheless copied eagerly, an
by quotemstr 7y ago
It's worth noting that on Linux, the address space itself is copy-on-write, but the page tables describing the address space are nevertheless copied eagerly, and this copying can take significant time. If you're going to be calling execve right after fork, you should be using vfork, not fork.
- mehrdadn 7y agoWhy don't people just use the standardized posix_spawn() or popen() in the first place? Why fork then exec?
- umanwizard 7y agoposix_spawn (at least in GNU/Linux) is a library function, not a syscall. Under the hood, it calls clone (which, like vfork, avoids copying page tables) and then execve. The reason fork (or vfork, or clone) and exec need to be separate steps is because you may want to do some stuff in between the two steps. The most obvious example is redirection: when you run "grep foo < bar", the shell needs to set stdin to point to "bar" before it execs "grep".
- mehrdadn 7y agoThanks but why don't people just use the portable posix_spawn when they can (which should be the vast majority of the time)? That it calls clone/execve underneath doesn't really answer my question...
- umanwizard 7y agoAs far as I know, there isn't any good reason not to. So indeed people should, if they can. (IIRC, posix_spawn was introduced relatively recently, so most old software wouldn't use it).
- manwe150 7y agoI was trying to find a year on it and couldn’t, but agree it seems newer. FWIW, it’s not required to be able to run any setup code in the child to do arbitrary setup. For instance, WinNT makes that very hard, but has a larger syscall interface to compensate, so it’s actually more general. An alternate design of running all code in the parent can be made work if the kernel supports passing a pid handle to every syscall: https://lwn.net/Articles/360747/ https://lwn.net/Articles/360747/ On the other hand, this is perhaps a bit more complex in some ways? or at least just different.
- cesarb 7y ago> I was trying to find a year on it and couldn’t, but agree it seems newer. http://man7.org/linux/man-pages/man3/posix_spawn.3.html#CONFORMING_TO http://man7.org/linux/man-pages/man3/posix_spawn.3.html#CONF... says POSIX.1-2001, so I'm guessing between 1998 and 2002 (according to https://en.wikipedia.org/wiki/Single_UNIX_Specification#2001:_Single_UNIX_Specification_version_3,_POSIX:2001 https://en.wikipedia.org/wiki/Single_UNIX_Specification#2001... it started development in 1998 and was released in 2002). That man page also says "since glibc 2.2", which according to Wikipedia was released November 2000.
- chrisseaton 7y agoSeems newer? Fork predates the whole idea of POSIX by decades, let alone the particular API posix_spawn.
- __s 7y agovfork isn't particularly of sound design: https://dwheeler.com/secure-programs/Secure-Programs-HOWTO/avoid-vfork.html https://dwheeler.com/secure-programs/Secure-Programs-HOWTO/a...
- quotemstr 7y agoWhat does "sound design" mean? If you'd said vfork is error prone, I might have agreed --- but lacking soundness suggests that it's not possible to use vfork correctly, and, well, it is possible to use vfork correctly.
- naniwaduni 7y agoIt is not possible to (usefully) use the former POSIX vfork correctly: > The vfork() function shall be equivalent to fork(), except that the behavior is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit() or one of the exec family of functions. This roughly simplifies to "the only safe thing to do after a vfork is exec", and in this decade you can use posix_spawnp for that instead. In particular, you can't do safely do anything that you'd normally want to after forking, like closing fds or moving them around (that'd be "calls any other function"). This means that unless the executable you're execing into is also under your control and knows what it's getting into, you have to mangle your fds &c. in the parent, vfork-and-exec, then undo the mess you've just made. It is in principle _possible_ to navigate this error-prone process without observable side-effects. (The same could be said about implementing speculative execution, and look where we are now.) But I would hesitate to call it correct; the approach is clearly wrong, even if the result looks okay.. The situation is only slightly better if you're targetting some particular OS, which can provide stronger guarantees.
- quotemstr 7y agoPOSIX is frequently hyperconservative garbage. There's what POSIX allows, and there's what Linux and other real Unix systems actually allow. How do you think posix_spawnnp is implemented on systems that don't have a native system call for it? vfork(2)! close(2) in practice works fine. I don't understand how you can claim that vfork can't be used correctly when there are thousands of existence proofs showing that it works fine.
- 01100011 7y agoYeah this. We had problems on an embedded system running python where things started breaking when the system was low on memory, but not so low that things should have failed. We ended up writing a posix_spawn() wrapper to avoid the OOM caused by duplicating the page table. I think it's weird Python doesn't do that by default when you're just launching an external command.