When a process calls vfork
, the parent remains in state D as long as the child hasn't executed _exit
or execve
(the only two authorized functions, together with execve
's relatives like execvp
, etc.). The parent is still executing the vfork
call, so it's in state D.
If the child does something like this (which is stupid, but valid), the parent will remain in state D indefinitely, while the child will remain in state R indefinitely.
if (!vfork()) while (1) {}
There's a flag you can set on a file descriptor (upon open()
: O_CLOEXEC or later with fcntl()
: FD_CLOEXEC) if you don't want that fd to be passed to executed commands.
That's what you should do for your internal file descriptors if you're going to execute commands.
In shells, that's what ksh93
does when you do exec 3< some-file
for instance. For other shells or fds opened with { cmd1; cmd2; } 3< file
, you'd need to close by hand if you don't want cmd1
or cmd2
to access that fd: {cmd1 3<&-; cmd2; } 3< file
. That's good practice but not always followed as it's usually not critical if you don't do it.
Now, whether the feature is useful. Yes, several commands rely on it.
A few commands take a file descriptor as argument that is meant to have been opened by a caller. A few examples that come to mind:
xterm
with its -S
option
qemu
for various things
flock
(to lock a file on the caller's fd)
- the
test
command aka [
for it's -t
option (OK the test
utility is built in most Bourne-like shells nowadays, but there still is a test
command that can be executed).
dialog
needs file descriptors for input from the user, output and error to the user and input and output to the caller, so you can use extra fds for that.
gpg
or openssl
to which you can specify a file descriptor to communicate the passphrase or other information.
There are a number of helper utilities (for instance, the need to execute could be to run a part of a command as a different user or group using a setuid/setgid executable) that rely on that.
Process substitution relies on it:
In, diff <(cmd1) <(cmd2)
, 2 file descriptors (to pipes) are passed to diff
and diff accesses them by opening them via the special /dev/fd/n passed as argument.
For shells that don't have process substitution, you do the same by hand with things like:
cm1 | { cmd2 | diff /dev/fd/3 -; } 3<&0
Best Answer
Yes, via
memfd_create
andfexecve
: