Reputation: 131646
I've just read this:
What does the FD_CLOEXEC fcntl() flag do?
and I understand what FD_CLOEXEC
does, but not why it's important. Why not just close all the relevant file descriptors before exec()
ing something? And why is it so critical to set FD_CLOEXEC
that there's a special O_CLOEXEC
open mode flag you can set (on Linux 2.6.something and later), only to avoid a bit of inter-thread synchronization?
Upvotes: 4
Views: 1978
Reputation: 428
Assume parent process P has a certain amount of files it shares with child process C1 (call it S1) and another amount of files it shares with child process C2 (call it S2).
This requires to NOT use CLOEXEC for those files with the open
call or whatever other call is used.
After the parent process opened the shared files S1, it calls fork/vfork/clone with the corresponding flags to inherit file descriptors. The same happens for the shared files S2. However, C2 now has also all file descriptors of C1.
Subsequent child processes C3...Cn would all inherit the file handles of previous processes, which is a problem if one works with many files and they are not closed shortly after.
One could now
The only exception, where file descriptor inheritance is the expected behavior are standard streams, because the user wants to handle child process output of errors or status reports.
Upvotes: 0
Reputation: 78
I have a use case, albeit one from a toy program (actually a homework assignment).
The assignment was to write a program that would take two arguments, which are the names of executables. It would start them up, using fork
and exec
(or e.g. execve
), with the stdout
of the first program writing to one end of a pipe that was read as stdin
of the second program.
Example usage: ./mypipeprogram ./program1 ./program2
should give results identical(ish) to ./program1 | ./program2
.
I wanted my program to be as close to bulletproof as I could get it, and that meant handling all the errors that I could, as gracefully as I could.
You'll have to forgive me, as I don't think I have the source anymore, so this is from memory.
One of the kinds of errors I had to try to handle was the case where one of the programs listed couldn't be exec
'd, but the other could. In that case, the process that couldn't exec
could kill
the other process, so it wouldn't hang forever, or anything like that.
In hindsight, probably not the best idea, because closing the pipe should have worked fine.
Still, going one way (I think it was the first process, the output one), I could catch this, and instead kill
the other process before it even tried to exec
the other program.
What I did was open another pipe, and fnctl
it with FD_CLOEXEC
, relying on POSIX saying that "the file shall be closed upon successful execution of one of the exec functions."
Then the second process would prepare to exec
, read from that pipe, and when it was closed, it would know the first process successfully exec
'd, so it could go ahead. If the first process's exec
failed, the pipe would still be open, so the second process would still be blocked on the read, and the first process could kill
it.
I used FD_CLOEXEC
on a pipe to allow one process to wait for a second process to successfully exec
, or get kill
ed by the second process if the exec
failed.
Upvotes: 1