#include <signal.h>
+void
+Perl_setfd_cloexec(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(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_cloexec_for_nonsysfd(pTHX_ int fd)
+{
+ assert(fd >= 0);
+ if(fd > PL_maxsysfd)
+ setfd_cloexec(fd);
+}
+
+void
+Perl_setfd_inhexec_for_sysfd(pTHX_ int fd)
+{
+ assert(fd >= 0);
+ if(fd <= PL_maxsysfd)
+ setfd_inhexec(fd);
+}
+void
+Perl_setfd_cloexec_or_inhexec_by_sysfdness(pTHX_ int fd)
+{
+ assert(fd >= 0);
+ if(fd <= PL_maxsysfd)
+ setfd_inhexec(fd);
+ else
+ setfd_cloexec(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) { \
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; \
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)
#endif
}
+int
+Perl_my_mkstemp_cloexec(char *templte)
+{
+ PERL_ARGS_ASSERT_MY_MKSTEMP_CLOEXEC;
+#if defined(O_CLOEXEC)
+ DO_ONEOPEN_EXPERIMENTING_CLOEXEC(
+ Perl_my_mkostemp(templte, O_CLOEXEC),
+ Perl_my_mkstemp(templte));
+#else
+ DO_ONEOPEN_THEN_CLOEXEC(Perl_my_mkstemp(templte));
+#endif
+}
+
#ifdef HAS_PIPE
int
Perl_PerlProc_pipe_cloexec(pTHX_ int *pipefd)
}
else {
if (dodup)
- wanted_fd = PerlLIO_dup(wanted_fd);
+ wanted_fd = PerlLIO_dup_cloexec(wanted_fd);
else
was_fdopen = TRUE;
if (!(fp = PerlIO_openn(aTHX_ type,mode,wanted_fd,0,0,NULL,num_svs,svp))) {
if (was_fdopen) {
/* need to close fp without closing underlying fd */
int ofd = PerlIO_fileno(fp);
- int dupfd = ofd >= 0 ? PerlLIO_dup(ofd) : -1;
-#if defined(HAS_FCNTL) && defined(F_SETFD)
- /* Assume if we have F_SETFD we have F_GETFD. */
- /* Get a copy of all the fd flags. */
- int fd_flags = ofd >= 0 ? fcntl(ofd, F_GETFD) : -1;
- if (fd_flags < 0) {
- if (dupfd >= 0)
- PerlLIO_close(dupfd);
- goto say_false;
- }
-#endif
+ int dupfd = ofd >= 0 ? PerlLIO_dup_cloexec(ofd) : -1;
if (ofd < 0 || dupfd < 0) {
if (dupfd >= 0)
PerlLIO_close(dupfd);
goto say_false;
}
PerlIO_close(fp);
- PerlLIO_dup2(dupfd, ofd);
-#if defined(HAS_FCNTL) && defined(F_SETFD)
- /* The dup trick has lost close-on-exec on ofd,
- * and possibly any other flags, so restore them. */
- if (fcntl(ofd,F_SETFD, fd_flags) < 0) {
- if (dupfd >= 0)
- PerlLIO_close(dupfd);
- goto say_false;
- }
-#endif
+ PerlLIO_dup2_cloexec(dupfd, ofd);
+ setfd_inhexec_for_sysfd(ofd);
PerlLIO_close(dupfd);
}
else
PerlIO_clearerr(fp);
fd = PerlIO_fileno(fp);
}
-#if defined(HAS_FCNTL) && defined(F_SETFD) && defined(FD_CLOEXEC)
- if (fd >= 0 && fd > PL_maxsysfd && fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
- PerlLIO_close(fd);
- goto say_false;
- }
-#endif
IoIFP(io) = fp;
IoFLAGS(io) &= ~IOf_NOLINE;
{
int old_umask = umask(0177);
- fd = Perl_my_mkstemp(SvPVX(temp_out_name));
+ fd = Perl_my_mkstemp_cloexec(SvPVX(temp_out_name));
umask(old_umask);
}