From: RĂ©mi Denis-Courmont Date: Sun, 8 Nov 2009 10:38:41 +0000 (+0200) Subject: Linux: create sockets with close-on-exec flag in thread-safe manner X-Git-Tag: 1.1.0-ff~2557 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=303fbc7c9c9246918eebeb4cbcd04a9b5e50f90f;p=vlc Linux: create sockets with close-on-exec flag in thread-safe manner There is a window of opportunity to leak file descriptors between their creation and the fcntl(FD_CLOEXEC) call. If another thread forks during this window, the descriptors will not have a the close-on-exec flag, and get leaked after exec(). This is a limitation of POSIX. While we're using the Linux-specific SOCK_CLOEXEC, we might as well use SOCK_NONBLOCK, and spare ourselves the three fcntl() calls. --- diff --git a/src/network/io.c b/src/network/io.c index 313e0e8a94..c326adc383 100644 --- a/src/network/io.c +++ b/src/network/io.c @@ -96,15 +96,29 @@ int net_SetupSocket (int fd) int net_Socket (vlc_object_t *p_this, int family, int socktype, int protocol) { - int fd = socket (family, socktype, protocol); - if (fd == -1) + int fd; + +#ifdef SOCK_CLOEXEC + fd = socket (family, socktype | SOCK_NONBLOCK | SOCK_CLOEXEC, protocol); + if (fd == -1 && errno == EINVAL) +#endif { - if (net_errno != EAFNOSUPPORT) - msg_Err (p_this, "cannot create socket: %m"); - return -1; + fd = socket (family, socktype, protocol); + if (fd == -1) + { + if (net_errno != EAFNOSUPPORT) + msg_Err (p_this, "cannot create socket: %m"); + return -1; + } +#ifndef WIN32 + fcntl (fd, F_SETFD, FD_CLOEXEC); + fcntl (fd, F_SETFL, fcntl (fd, F_GETFL, 0) | O_NONBLOCK); +#else + ioctlsocket (fd, FIONBIO, &(unsigned long){ 1 }); +#endif } - net_SetupSocket (fd); + setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof (int)); #ifdef IPV6_V6ONLY /*