Search code examples
c++cprocessposixspawn

Is there a difference between setting FD_CLOEXEC on a file descriptor vs. passing it to posix_spawn_file_actions_addclose?


I have some code that's using posix_spawnp(3) to create a new process. I want to set the child's stdin to read from a certain file descriptor so before the posix_spawnp() call I'm setting up a dup2 file action:

ret = posix_spawn_file_actions_adddup2(&file_actions, fd_for_stdin, 0);

Then I have no more use for fd_for_stdin in the child process so I believe I should close it. To achieve that is there a difference between adding a call to posix_spawn_file_actions_addclose(3) versus adding a call to fcntl(2) to set FD_CLOEXEC? My understanding is that these two code snippets (error checking omitted) should have the same result - is that right, or am I missing something?

posix_spawn_file_actions_adddup2(&file_actions, fd_for_stdin, STDIN_FILENO);
posix_spawn_file_actions_addclose(&file_actions, fd_for_stdin);
posix_spawnp(..., &file_actions, ...);

Versus:

posix_spawn_file_actions_adddup2(&file_actions, fd_for_stdin, STDIN_FILENO);
fcntl(fd_for_stdin, F_SETFD, FD_CLOEXEC);
posix_spawnp(..., &file_actions, ...);

Solution

  • The spec of posix_spawnp() says:

    1. The set of open file descriptors for the child process shall initially be the same set as is open for the calling process. The child process shall not inherit any file locks, but all remaining attributes of the corresponding open file descriptions (see fcntl), shall remain unchanged.

    2. The signal mask, signal default actions, and the effective user and group IDs for the child process shall be changed as specified in the attributes object referenced by attrp.

    3. The file actions specified by the spawn file actions object shall be performed in the order in which they were added to the spawn file actions object.

    4. Any file descriptor that has its FD_CLOEXEC flag set (see fcntl) shall be closed.

    There's nothing in the description of the close action that suggests that it does anything different from the FD_CLOEXEC flag. In both cases they just close the descriptor when spawning.

    However, using posix_spawn_file_actions_addclose() gives you control over precisely when the descriptor is closed, since the file actions are performed in the order that they're added, while FD_CLEXEC is always processed last.