pbn pbn - 2 months ago 18
C Question

Difference between O_CLOEXEC and TIOCEXCL

I use a device on serial port /dev/ttyUSB0 (uses FTDI) and I don't want to leak any file descriptors to other spawned processes so I set the close-on-exec flag on the descriptor. Could you tell me what is the difference between setting O_CLOEXEC while opening:

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int fd, rc;
fd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY | O_CLOEXEC);
if(fd < 0)
{
perror("error open:");
exit(-1);
}
rc = close(fd);
if(rc != 0)
{
perror("error close:");
exit(-1);
}

return 0;
}


And setting close-on-exec with ioctl(fd, TIOCEXCL):

#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
int fd, rc;

fd = open("/dev/ttyUSB1", O_RDWR | O_NOCTTY);
if(fd < 0)
{
perror("error open:");
exit(-1);
}

rc = ioctl(fd, TIOCEXCL);
if(rc != 0)
{
perror("error ioctl:");
exit(-1);
}

rc = close(fd);
if(rc != 0)
{
perror("error close:");
exit(-1);
}

return 0;
}

Answer

The TIOCEXCL does not set the close-on-exec flag (that would be FIOCLEX, or, equivalently, fcntl(fd, F_SETFD, FD_CLOEXEC)).

To answer the question you thought you were asking:

Specifying O_CLOEXEC when you open() a file will set the close-on-exec flag before it returns, saving you another call and, importantly, ensuring that there is no race condition where another thread might call exec() after open() but before the subsequent fcntl().

If you really need to set or unset the flag at any other time (I've never needed to), you can do so with fcntl F_SETFD, passing FD_CLOEXEC or 0 respectively.