From: Eric Engestrom Date: Thu, 4 Jun 2020 23:08:33 +0000 (+0200) Subject: util: introduce os_dupfd_cloexec() helper X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=commitdiff_plain;h=0e5ea7a36399815a2e39b72f3f0e3a75c44c062d util: introduce os_dupfd_cloexec() helper Adapted from wayland's wl_os_dupfd_cloexec(). Suggested-by: Kristian H. Kristensen Signed-off-by: Eric Engestrom Reviewed-by: Kristian H. Kristensen Reviewed-by: Lionel Landwerlin Part-of: --- diff --git a/src/util/os_file.c b/src/util/os_file.c index f02d74afd2c..c5970ddb243 100644 --- a/src/util/os_file.c +++ b/src/util/os_file.c @@ -18,6 +18,11 @@ #define O_CREAT _O_CREAT #define O_EXCL _O_EXCL #define O_WRONLY _O_WRONLY +#else +#include +#ifndef F_DUPFD_CLOEXEC +#define F_DUPFD_CLOEXEC 1030 +#endif #endif @@ -31,6 +36,50 @@ os_file_create_unique(const char *filename, int filemode) } +#if DETECT_OS_WINDOWS +int +os_dupfd_cloexec(int fd) +{ + /* + * On Windows child processes don't inherit handles by default: + * https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873 + */ + return dup(fd); +} +#else +int +os_dupfd_cloexec(int fd) +{ + int minfd = 3; + int newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd); + + if (newfd >= 0) + return newfd; + + if (errno != EINVAL) + return -1; + + newfd = fcntl(fd, F_DUPFD, minfd); + + if (newfd < 0) + return -1; + + long flags = fcntl(newfd, F_GETFD); + if (flags == -1) { + close(newfd); + return -1; + } + + if (fcntl(newfd, F_SETFD, flags | FD_CLOEXEC) == -1) { + close(newfd); + return -1; + } + + return newfd; +} +#endif + + #if DETECT_OS_LINUX #include diff --git a/src/util/os_file.h b/src/util/os_file.h index 36f367ea358..cf0dc207595 100644 --- a/src/util/os_file.h +++ b/src/util/os_file.h @@ -24,6 +24,12 @@ extern "C" { FILE * os_file_create_unique(const char *filename, int filemode); +/* + * Duplicate a file descriptor, making sure not to keep it open after an exec*() + */ +int +os_dupfd_cloexec(int fd); + /* * Read a file. * Returns a char* that the caller must free(), or NULL and sets errno.