diff options
author | Zefram <zefram@fysh.org> | 2017-12-19 16:53:39 +0000 |
---|---|---|
committer | Zefram <zefram@fysh.org> | 2017-12-22 16:13:23 +0000 |
commit | 74df577f6857d2d8543c90e43f90405f92948a61 (patch) | |
tree | af79ab48854bb2583b061679690f55c33ce0115f /doio.c | |
parent | f9821aff984443d5ac38188fab7a9b12dd3cb09c (diff) | |
download | perl-74df577f6857d2d8543c90e43f90405f92948a61.tar.gz |
set FD_CLOEXEC atomically in easy cases
In many places where a file descriptor is being opened, open it with
FD_CLOEXEC already set if possible. This commit covers the easy cases,
where the file descriptor arises without the use of PerlIO, pp_open,
or my_popen.
Diffstat (limited to 'doio.c')
-rw-r--r-- | doio.c | 57 |
1 files changed, 39 insertions, 18 deletions
@@ -60,22 +60,43 @@ #include <signal.h> +void +Perl_setfd_cloexec(pTHX_ int fd) +{ + assert(fd >= 0); #if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) -# define DO_ONESET_CLOEXEC(fd) ((void) fcntl(fd, F_SETFD, FD_CLOEXEC)) -#else -# define DO_ONESET_CLOEXEC(fd) ((void) 0) + (void) fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +} + +void +Perl_setfd_inhexec(pTHX_ int fd) +{ + assert(fd >= 0); +#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) + (void) fcntl(fd, F_SETFD, 0); #endif -#define DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSET_CLOEXEC) \ +} + +void +Perl_setfd_inhexec_for_sysfd(pTHX_ int fd) +{ + assert(fd >= 0); + if(fd <= PL_maxsysfd) + setfd_inhexec(fd); +} + +#define DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSETFD_CLOEXEC) \ do { \ int res = (GENOPEN_NORMAL); \ - if(LIKELY(res != -1)) GENSET_CLOEXEC; \ + if(LIKELY(res != -1)) GENSETFD_CLOEXEC; \ return res; \ } while(0) #if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC) && \ defined(F_GETFD) enum { CLOEXEC_EXPERIMENT, CLOEXEC_AT_OPEN, CLOEXEC_AFTER_OPEN }; # define DO_GENOPEN_EXPERIMENTING_CLOEXEC(TESTFD, GENOPEN_CLOEXEC, \ - GENOPEN_NORMAL, GENSET_CLOEXEC) \ + GENOPEN_NORMAL, GENSETFD_CLOEXEC) \ do { \ static int strategy = CLOEXEC_EXPERIMENT; \ switch (strategy) { \ @@ -88,14 +109,14 @@ enum { CLOEXEC_EXPERIMENT, CLOEXEC_AT_OPEN, CLOEXEC_AFTER_OPEN }; strategy = CLOEXEC_AT_OPEN; \ } else { \ strategy = CLOEXEC_AFTER_OPEN; \ - GENSET_CLOEXEC; \ + GENSETFD_CLOEXEC; \ } \ } else if (UNLIKELY((eno = errno) == EINVAL || \ eno == ENOSYS)) { \ res = (GENOPEN_NORMAL); \ if (LIKELY(res != -1)) { \ strategy = CLOEXEC_AFTER_OPEN; \ - GENSET_CLOEXEC; \ + GENSETFD_CLOEXEC; \ } else if (!LIKELY((eno = errno) == EINVAL || \ eno == ENOSYS)) { \ strategy = CLOEXEC_AFTER_OPEN; \ @@ -106,39 +127,39 @@ enum { CLOEXEC_EXPERIMENT, CLOEXEC_AT_OPEN, CLOEXEC_AFTER_OPEN }; case CLOEXEC_AT_OPEN: \ return (GENOPEN_CLOEXEC); \ case CLOEXEC_AFTER_OPEN: \ - DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSET_CLOEXEC); \ + DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSETFD_CLOEXEC); \ } \ } while(0) #else # define DO_GENOPEN_EXPERIMENTING_CLOEXEC(TESTFD, GENOPEN_CLOEXEC, \ - GENOPEN_NORMAL, GENSET_CLOEXEC) \ - DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSET_CLOEXEC) + GENOPEN_NORMAL, GENSETFD_CLOEXEC) \ + DO_GENOPEN_THEN_CLOEXEC(GENOPEN_NORMAL, GENSETFD_CLOEXEC) #endif #define DO_ONEOPEN_THEN_CLOEXEC(ONEOPEN_NORMAL) \ do { \ int fd; \ DO_GENOPEN_THEN_CLOEXEC(fd = (ONEOPEN_NORMAL), \ - DO_ONESET_CLOEXEC(fd)); \ + setfd_cloexec(fd)); \ } while(0) #define DO_ONEOPEN_EXPERIMENTING_CLOEXEC(ONEOPEN_CLOEXEC, ONEOPEN_NORMAL) \ do { \ int fd; \ DO_GENOPEN_EXPERIMENTING_CLOEXEC(fd, fd = (ONEOPEN_CLOEXEC), \ - fd = (ONEOPEN_NORMAL), DO_ONESET_CLOEXEC(fd)); \ + fd = (ONEOPEN_NORMAL), setfd_cloexec(fd)); \ } while(0) -#define DO_PIPESET_CLOEXEC(PIPEFD) \ +#define DO_PIPESETFD_CLOEXEC(PIPEFD) \ do { \ - DO_ONESET_CLOEXEC((PIPEFD)[0]); \ - DO_ONESET_CLOEXEC((PIPEFD)[1]); \ + setfd_cloexec((PIPEFD)[0]); \ + setfd_cloexec((PIPEFD)[1]); \ } while(0) #define DO_PIPEOPEN_THEN_CLOEXEC(PIPEFD, PIPEOPEN_NORMAL) \ - DO_GENOPEN_THEN_CLOEXEC(PIPEOPEN_NORMAL, DO_PIPESET_CLOEXEC(PIPEFD)) + DO_GENOPEN_THEN_CLOEXEC(PIPEOPEN_NORMAL, DO_PIPESETFD_CLOEXEC(PIPEFD)) #define DO_PIPEOPEN_EXPERIMENTING_CLOEXEC(PIPEFD, PIPEOPEN_CLOEXEC, \ PIPEOPEN_NORMAL) \ DO_GENOPEN_EXPERIMENTING_CLOEXEC((PIPEFD)[0], PIPEOPEN_CLOEXEC, \ - PIPEOPEN_NORMAL, DO_PIPESET_CLOEXEC(PIPEFD)) + PIPEOPEN_NORMAL, DO_PIPESETFD_CLOEXEC(PIPEFD)) int Perl_PerlLIO_dup_cloexec(pTHX_ int oldfd) |