Why does closing file descriptors after fork affect the child process?

孤者浪人 提交于 2019-12-05 10:15:54
D3Hunter

First problem: There is no way to prevent inheritance of file descriptors except you close them yourself or set FD_CLOEXEC, check this

Second problem: You got The return value of waitpid is often 0, because you sepecfied WNOHANG in waitpid.

waitpid(): on success, returns the process ID of the child whose state has changed; 
if WNOHANG was specified  and  one  or  more  child(ren) specified by pid exist, 
but have not yet changed state, then 0 is returned.  On error, -1 is returned.

First, in 2014, never use vfork but simply fork(2). (Since vfork(2) is obsolete since POSIX 2001 and removed in POSIX 2008).

Then, the simplest way to close most of file descriptors is just

for (int fd=3; fd<256; fd++) (void) close(fd);

(hint: if a fd is invalid, close(fd) would fail and we ignore the failure; and you start from 3 to keep open 0==stdin, 1==stdout, 2==stderr; so in principle all the close above would fail).

However, well behaved and well-written programs should not need such a loop on closing (so it is a crude way to overcome previous bugs).

Of course, if you know that some file descriptor other than stdin, stdout, stderr is valid and needed to the child program_call (which is unlikely) you'll need to explicitly skip it.

and then use FD_CLOEXEC as much as possible.

It is unlikely that your program would have a lot of file descriptors without you knowing them.

Maybe you want daemon(3) or (as commented by vality) posix_spawn.

If you need to explicitly close STDIN_FILENO (i.e. 0), or STDOUT_FILENO (i.e. 1), or STDERR_FILENO (i.e. 2) you'll better open("/dev/null",... and dup2 them after - before calling exec, because most programs expect them to exist.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!