95

Like so:

if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
...

Though I've read man fcntl, I can't figure out what it does.

unwind
  • 391,730
  • 64
  • 469
  • 606
compile-fan
  • 16,885
  • 22
  • 59
  • 73

2 Answers2

91

It sets the close-on-exec flag for the file descriptor, which causes the file descriptor to be automatically (and atomically) closed when any of the exec-family functions succeed.

It also tests the return value to see if the operation failed, which is rather useless if the file descriptor is valid, since there is no condition under which this operation should fail on a valid file descriptor.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 6
    Note that it does nothing about flushing any file stream (`FILE *`) associated with the file descriptor. One valid use for FD_CLOEXEC is to close a log file that the parent process has open when executing a shell process. Note that POSIX 2008 has an option to [`open(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html) for O_CLOEXEC - so you can set this property when you open the file, which will be very useful once it is widely available. – Jonathan Leffler May 25 '11 at 14:11
  • Setting the flag atomically when the file is opened is pretty much essential to any threaded program that might be opening files while another thread might be executing external programs. Unfortunately it's only available for `open` and not `accept`, `socket`, `pipe`, etc... – R.. GitHub STOP HELPING ICE May 25 '11 at 14:19
  • Yeah - there are design problems adding O_CLOEXEC or equivalent to the other file-descriptor creating functions (though `dup()` and `dup2()` are not affected, of course). You'd probably have to have new functions with an extra 'mode' or 'flags' parameter, which is presumably why it didn't happen. If you could use O_CLOEXEC on socket, then you could suppose that `accept()` would clone that flag on the descriptor it returns. But `socket()` and `pipe()` are trickier. – Jonathan Leffler May 25 '11 at 14:27
  • 3
    `dup` and `dup2` are affected. The close-on-exec flag applies to file descriptors, not open file descriptions, so it's not shared across duplicated file descriptors. That is a very good thing. – R.. GitHub STOP HELPING ICE May 25 '11 at 14:33
  • OK - my bad. I'd edit the comment but far too much time has elapsed to allow my to do so. – Jonathan Leffler May 25 '11 at 15:09
  • 3
    Following up on the conversation in the comments, POSIX has adopted for inclusion in the next issue new interfaces which fix the deficiencies: `dup3`, `pipe2`, and `accept4`. Also, `socket` has the `SOCK_CLOEXEC` flag you can combine with the requested socket type. – R.. GitHub STOP HELPING ICE Mar 10 '14 at 16:30
46

It marks the file descriptor so that it will be close()d automatically when the process or any children it fork()s calls one of the exec*() family of functions. This is useful to keep from leaking your file descriptors to random programs run by e.g. system().

geekosaur
  • 59,309
  • 11
  • 123
  • 114
  • Is this a security concern? – zach Jul 29 '17 at 11:14
  • 1
    @zach you could say so; but then really any refactoring you do, like encapsulating a scattered logic to a single entity, may be called a "security concern", because it reduces probability of bugs due to wrong usage of that entity, and "a bug" is an abstract thing that does include segfaults and information leaks in particular. – Hi-Angel Jan 10 '19 at 22:23
  • 1
    So I'm refactoring some socket code, and between getting the socket and connec()ing to the remote server they use F_SETFD to add the FD_CLOEXEC flag to the socket's FD. Then after a successful connect the FD_CLOEXEC is removed. I can't find any exec() calls involved in this area of code and I'm wondering if they're remnants of old code that should have been removed but weren't. Not sure what to look for to find out the purpose of it all. – JoeManiaci Aug 17 '20 at 20:57