GNU bug report logs - #14803
Setting close-on-exec flag consistently

Previous Next

Package: emacs;

Reported by: Paul Eggert <eggert <at> cs.ucla.edu>

Date: Sat, 6 Jul 2013 09:14:02 UTC

Severity: normal

Tags: patch

Done: Paul Eggert <eggert <at> cs.ucla.edu>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 14803 in the body.
You can then email your comments to 14803 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#14803; Package emacs. (Sat, 06 Jul 2013 09:14:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Paul Eggert <eggert <at> cs.ucla.edu>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sat, 06 Jul 2013 09:14:03 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: bug-gnu-emacs <at> gnu.org
Subject: Setting close-on-exec flag consistently
Date: Sat, 06 Jul 2013 02:13:19 -0700
Tags: patch

Here's a patch I'd like to install into Emacs soon.
It changes Emacs so that it creates file descriptors
that are close-on-exec unless they are intended to
be propagated to child processes.
This patch may affect the Microsoft Windows ports
so I'm sending it to bug-gnu-emacs first.
Much of the new code is imported from gnulib.

=== modified file 'ChangeLog'
--- ChangeLog	2013-07-03 03:20:04 +0000
+++ ChangeLog	2013-07-06 08:31:57 +0000
@@ -1,3 +1,12 @@
+2013-07-06  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Make file descriptors close-on-exec when possible.
+	* configure.ac (mkostemp): New function to check for.
+	(PTY_OPEN): Pass O_CLOEXEC to posix_openpt.
+	* lib/fcntl.c, lib/getdtablesize.c, lib/pipe2.c, m4/fcntl.m4:
+	* m4/getdtablesize.m4, m4/pipe2.m4: New files, taken from gnulib.
+	* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
+
 2013-07-03  Christoph Egger  <christoph <at> debian.org>  (tiny change)
 
 	* configure.ac (emacs_broken_SIGIO): Set on gnu-kfreebsd to avoid hang.

=== modified file 'admin/ChangeLog'
--- admin/ChangeLog	2013-07-06 02:32:13 +0000
+++ admin/ChangeLog	2013-07-06 08:31:57 +0000
@@ -1,3 +1,9 @@
+2013-07-06  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Make file descriptors close-on-exec when possible.
+	* merge-gnulib (GNULIB_MODULES): Add fcntl, pipe2.
+	(GNULIB_TOOL_FLAGS): Avoid binary-io, close.  Do not avoid fcntl.
+
 2013-07-06  Glenn Morris  <rgm <at> gnu.org>
 
 	* admin.el (manual-misc-manuals): New function.

=== modified file 'admin/merge-gnulib'
--- admin/merge-gnulib	2013-05-07 21:34:03 +0000
+++ admin/merge-gnulib	2013-07-06 07:04:07 +0000
@@ -29,11 +29,11 @@
   alloca-opt c-ctype c-strcase
   careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
   dtoastr dtotimespec dup2 environ execinfo faccessat
-  fcntl-h fdatasync fdopendir filemode fstatat fsync
+  fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync
   getloadavg getopt-gnu gettime gettimeofday
   ignore-value intprops largefile lstat
   manywarnings memrchr mktime
-  pselect pthread_sigmask putenv qacl readlink readlinkat
+  pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat
   sig2str socklen stat-time stdalign stdarg stdbool stdio
   strftime strtoimax strtoumax symlink sys_stat
   sys_time time timer-time timespec-add timespec-sub unsetenv utimens
@@ -41,8 +41,8 @@
 '
 
 GNULIB_TOOL_FLAGS='
-  --avoid=dup
-  --avoid=fchdir --avoid=fcntl --avoid=fstat
+  --avoid=binary-io --avoid=close --avoid=dup
+  --avoid=fchdir --avoid=fstat
   --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow
   --avoid=open --avoid=openat-die --avoid=opendir
   --avoid=raise

=== modified file 'configure.ac'
--- configure.ac	2013-07-03 03:20:04 +0000
+++ configure.ac	2013-07-06 07:04:07 +0000
@@ -3244,7 +3244,7 @@
 getrlimit setrlimit shutdown getaddrinfo \
 strsignal setitimer \
 sendto recvfrom getsockname getpeername getifaddrs freeifaddrs \
-gai_strerror mkstemp getline getdelim sync \
+gai_strerror mkostemp mkstemp getline getdelim sync \
 difftime posix_memalign \
 getpwent endpwent getgrent endgrent \
 touchlock \
@@ -3934,7 +3934,7 @@
       AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptyname = 0; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); if (grantpt (fd) != -1 && unlockpt (fd) != -1) ptyname = ptsname(fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (!ptyname) { close (fd); return -1; } snprintf (pty_name, sizeof pty_name, "%s", ptyname); }])
       dnl if HAVE_POSIX_OPENPT
       if test "x$ac_cv_func_posix_openpt" = xyes; then
-        AC_DEFINE(PTY_OPEN, [fd = posix_openpt (O_RDWR | O_NOCTTY)])
+        AC_DEFINE(PTY_OPEN, [fd = posix_openpt (O_RDWR | O_CLOEXEC | O_NOCTTY)])
         AC_DEFINE(PTY_NAME_SPRINTF, [])
       dnl if HAVE_GETPT
       elif test "x$ac_cv_func_getpt" = xyes; then

=== added file 'lib/fcntl.c'
--- lib/fcntl.c	1970-01-01 00:00:00 +0000
+++ lib/fcntl.c	2013-07-06 07:04:07 +0000
@@ -0,0 +1,311 @@
+/* Provide file descriptor control.
+
+   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake <ebb9 <at> byu.net>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <fcntl.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#if !HAVE_FCNTL
+# define rpl_fcntl fcntl
+#endif
+#undef fcntl
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Get declarations of the native Windows API functions.  */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+/* Get _get_osfhandle.  */
+# include "msvc-nothrow.h"
+
+/* Upper bound on getdtablesize().  See lib/getdtablesize.c.  */
+# define OPEN_MAX_MAX 0x10000
+
+/* Duplicate OLDFD into the first available slot of at least NEWFD,
+   which must be positive, with FLAGS determining whether the duplicate
+   will be inheritable.  */
+static int
+dupfd (int oldfd, int newfd, int flags)
+{
+  /* Mingw has no way to create an arbitrary fd.  Iterate until all
+     file descriptors less than newfd are filled up.  */
+  HANDLE curr_process = GetCurrentProcess ();
+  HANDLE old_handle = (HANDLE) _get_osfhandle (oldfd);
+  unsigned char fds_to_close[OPEN_MAX_MAX / CHAR_BIT];
+  unsigned int fds_to_close_bound = 0;
+  int result;
+  BOOL inherit = flags & O_CLOEXEC ? FALSE : TRUE;
+  int mode;
+
+  if (newfd < 0 || getdtablesize () <= newfd)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (old_handle == INVALID_HANDLE_VALUE
+      || (mode = setmode (oldfd, O_BINARY)) == -1)
+    {
+      /* oldfd is not open, or is an unassigned standard file
+         descriptor.  */
+      errno = EBADF;
+      return -1;
+    }
+  setmode (oldfd, mode);
+  flags |= mode;
+
+  for (;;)
+    {
+      HANDLE new_handle;
+      int duplicated_fd;
+      unsigned int index;
+
+      if (!DuplicateHandle (curr_process,           /* SourceProcessHandle */
+                            old_handle,             /* SourceHandle */
+                            curr_process,           /* TargetProcessHandle */
+                            (PHANDLE) &new_handle,  /* TargetHandle */
+                            (DWORD) 0,              /* DesiredAccess */
+                            inherit,                /* InheritHandle */
+                            DUPLICATE_SAME_ACCESS)) /* Options */
+        {
+          /* TODO: Translate GetLastError () into errno.  */
+          errno = EMFILE;
+          result = -1;
+          break;
+        }
+      duplicated_fd = _open_osfhandle ((intptr_t) new_handle, flags);
+      if (duplicated_fd < 0)
+        {
+          CloseHandle (new_handle);
+          errno = EMFILE;
+          result = -1;
+          break;
+        }
+      if (newfd <= duplicated_fd)
+        {
+          result = duplicated_fd;
+          break;
+        }
+
+      /* Set the bit duplicated_fd in fds_to_close[].  */
+      index = (unsigned int) duplicated_fd / CHAR_BIT;
+      if (fds_to_close_bound <= index)
+        {
+          if (sizeof fds_to_close <= index)
+            /* Need to increase OPEN_MAX_MAX.  */
+            abort ();
+          memset (fds_to_close + fds_to_close_bound, '\0',
+                  index + 1 - fds_to_close_bound);
+          fds_to_close_bound = index + 1;
+        }
+      fds_to_close[index] |= 1 << ((unsigned int) duplicated_fd % CHAR_BIT);
+    }
+
+  /* Close the previous fds that turned out to be too small.  */
+  {
+    int saved_errno = errno;
+    unsigned int duplicated_fd;
+
+    for (duplicated_fd = 0;
+         duplicated_fd < fds_to_close_bound * CHAR_BIT;
+         duplicated_fd++)
+      if ((fds_to_close[duplicated_fd / CHAR_BIT]
+           >> (duplicated_fd % CHAR_BIT))
+          & 1)
+        close (duplicated_fd);
+
+    errno = saved_errno;
+  }
+
+# if REPLACE_FCHDIR
+  if (0 <= result)
+    result = _gl_register_dup (oldfd, result);
+# endif
+  return result;
+}
+#endif /* W32 */
+
+/* Perform the specified ACTION on the file descriptor FD, possibly
+   using the argument ARG further described below.  This replacement
+   handles the following actions, and forwards all others on to the
+   native fcntl.  An unrecognized ACTION returns -1 with errno set to
+   EINVAL.
+
+   F_DUPFD - duplicate FD, with int ARG being the minimum target fd.
+   If successful, return the duplicate, which will be inheritable;
+   otherwise return -1 and set errno.
+
+   F_DUPFD_CLOEXEC - duplicate FD, with int ARG being the minimum
+   target fd.  If successful, return the duplicate, which will not be
+   inheritable; otherwise return -1 and set errno.
+
+   F_GETFD - ARG need not be present.  If successful, return a
+   non-negative value containing the descriptor flags of FD (only
+   FD_CLOEXEC is portable, but other flags may be present); otherwise
+   return -1 and set errno.  */
+
+int
+rpl_fcntl (int fd, int action, /* arg */...)
+{
+  va_list arg;
+  int result = -1;
+  va_start (arg, action);
+  switch (action)
+    {
+
+#if !HAVE_FCNTL
+    case F_DUPFD:
+      {
+        int target = va_arg (arg, int);
+        result = dupfd (fd, target, 0);
+        break;
+      }
+#elif FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR
+    case F_DUPFD:
+      {
+        int target = va_arg (arg, int);
+        /* Detect invalid target; needed for cygwin 1.5.x.  */
+        if (target < 0 || getdtablesize () <= target)
+          errno = EINVAL;
+        else
+          {
+            /* Haiku alpha 2 loses fd flags on original.  */
+            int flags = fcntl (fd, F_GETFD);
+            if (flags < 0)
+              {
+                result = -1;
+                break;
+              }
+            result = fcntl (fd, action, target);
+            if (0 <= result && fcntl (fd, F_SETFD, flags) == -1)
+              {
+                int saved_errno = errno;
+                close (result);
+                result = -1;
+                errno = saved_errno;
+              }
+# if REPLACE_FCHDIR
+            if (0 <= result)
+              result = _gl_register_dup (fd, result);
+# endif
+          }
+        break;
+      } /* F_DUPFD */
+#endif /* FCNTL_DUPFD_BUGGY || REPLACE_FCHDIR */
+
+    case F_DUPFD_CLOEXEC:
+      {
+        int target = va_arg (arg, int);
+
+#if !HAVE_FCNTL
+        result = dupfd (fd, target, O_CLOEXEC);
+        break;
+#else /* HAVE_FCNTL */
+        /* Try the system call first, if the headers claim it exists
+           (that is, if GNULIB_defined_F_DUPFD_CLOEXEC is 0), since we
+           may be running with a glibc that has the macro but with an
+           older kernel that does not support it.  Cache the
+           information on whether the system call really works, but
+           avoid caching failure if the corresponding F_DUPFD fails
+           for any reason.  0 = unknown, 1 = yes, -1 = no.  */
+        static int have_dupfd_cloexec = GNULIB_defined_F_DUPFD_CLOEXEC ? -1 : 0;
+        if (0 <= have_dupfd_cloexec)
+          {
+            result = fcntl (fd, action, target);
+            if (0 <= result || errno != EINVAL)
+              {
+                have_dupfd_cloexec = 1;
+# if REPLACE_FCHDIR
+                if (0 <= result)
+                  result = _gl_register_dup (fd, result);
+# endif
+              }
+            else
+              {
+                result = rpl_fcntl (fd, F_DUPFD, target);
+                if (result < 0)
+                  break;
+                have_dupfd_cloexec = -1;
+              }
+          }
+        else
+          result = rpl_fcntl (fd, F_DUPFD, target);
+        if (0 <= result && have_dupfd_cloexec == -1)
+          {
+            int flags = fcntl (result, F_GETFD);
+            if (flags < 0 || fcntl (result, F_SETFD, flags | FD_CLOEXEC) == -1)
+              {
+                int saved_errno = errno;
+                close (result);
+                errno = saved_errno;
+                result = -1;
+              }
+          }
+        break;
+#endif /* HAVE_FCNTL */
+      } /* F_DUPFD_CLOEXEC */
+
+#if !HAVE_FCNTL
+    case F_GETFD:
+      {
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+        HANDLE handle = (HANDLE) _get_osfhandle (fd);
+        DWORD flags;
+        if (handle == INVALID_HANDLE_VALUE
+            || GetHandleInformation (handle, &flags) == 0)
+          errno = EBADF;
+        else
+          result = (flags & HANDLE_FLAG_INHERIT) ? 0 : FD_CLOEXEC;
+# else /* !W32 */
+        /* Use dup2 to reject invalid file descriptors.  No way to
+           access this information, so punt.  */
+        if (0 <= dup2 (fd, fd))
+          result = 0;
+# endif /* !W32 */
+        break;
+      } /* F_GETFD */
+#endif /* !HAVE_FCNTL */
+
+      /* Implementing F_SETFD on mingw is not trivial - there is no
+         API for changing the O_NOINHERIT bit on an fd, and merely
+         changing the HANDLE_FLAG_INHERIT bit on the underlying handle
+         can lead to odd state.  It may be possible by duplicating the
+         handle, using _open_osfhandle with the right flags, then
+         using dup2 to move the duplicate onto the original, but that
+         is not supported for now.  */
+
+    default:
+      {
+#if HAVE_FCNTL
+        void *p = va_arg (arg, void *);
+        result = fcntl (fd, action, p);
+#else
+        errno = EINVAL;
+#endif
+        break;
+      }
+    }
+  va_end (arg);
+  return result;
+}

=== added file 'lib/getdtablesize.c'
--- lib/getdtablesize.c	1970-01-01 00:00:00 +0000
+++ lib/getdtablesize.c	2013-07-06 07:04:07 +0000
@@ -0,0 +1,86 @@
+/* getdtablesize() function for platforms that don't have it.
+   Copyright (C) 2008-2013 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno <at> clisp.org>, 2008.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+#include <stdio.h>
+
+#include "msvc-inval.h"
+
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+static int
+_setmaxstdio_nothrow (int newmax)
+{
+  int result;
+
+  TRY_MSVC_INVAL
+    {
+      result = _setmaxstdio (newmax);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = -1;
+    }
+  DONE_MSVC_INVAL;
+
+  return result;
+}
+# define _setmaxstdio _setmaxstdio_nothrow
+#endif
+
+/* Cache for the previous getdtablesize () result.  */
+static int dtablesize;
+
+int
+getdtablesize (void)
+{
+  if (dtablesize == 0)
+    {
+      /* We are looking for the number N such that the valid file descriptors
+         are 0..N-1.  It can be obtained through a loop as follows:
+           {
+             int fd;
+             for (fd = 3; fd < 65536; fd++)
+               if (dup2 (0, fd) == -1)
+                 break;
+             return fd;
+           }
+         On Windows XP, the result is 2048.
+         The drawback of this loop is that it allocates memory for a libc
+         internal array that is never freed.
+
+         The number N can also be obtained as the upper bound for
+         _getmaxstdio ().  _getmaxstdio () returns the maximum number of open
+         FILE objects.  The sanity check in _setmaxstdio reveals the maximum
+         number of file descriptors.  This too allocates memory, but it is
+         freed when we call _setmaxstdio with the original value.  */
+      int orig_max_stdio = _getmaxstdio ();
+      unsigned int bound;
+      for (bound = 0x10000; _setmaxstdio (bound) < 0; bound = bound / 2)
+        ;
+      _setmaxstdio (orig_max_stdio);
+      dtablesize = bound;
+    }
+  return dtablesize;
+}
+
+#endif

=== modified file 'lib/gnulib.mk'
--- lib/gnulib.mk	2013-05-07 21:34:03 +0000
+++ lib/gnulib.mk	2013-07-06 07:04:07 +0000
@@ -21,7 +21,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=dup --avoid=fchdir --avoid=fcntl --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings memrchr mktime pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_ti
 me time t
imer-time timespec-add timespec-sub unsetenv utimens warnings
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=binary-io --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings memrchr mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax str
 toumax sy
mlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings
 
 
 MOSTLYCLEANFILES += core *.stackdump
@@ -296,6 +296,15 @@
 
 ## end   gnulib module faccessat
 
+## begin gnulib module fcntl
+
+
+EXTRA_DIST += fcntl.c
+
+EXTRA_libgnu_a_SOURCES += fcntl.c
+
+## end   gnulib module fcntl
+
 ## begin gnulib module fcntl-h
 
 BUILT_SOURCES += fcntl.h
@@ -384,6 +393,17 @@
 
 ## end   gnulib module fsync
 
+## begin gnulib module getdtablesize
+
+if gl_GNULIB_ENABLED_getdtablesize
+
+endif
+EXTRA_DIST += getdtablesize.c
+
+EXTRA_libgnu_a_SOURCES += getdtablesize.c
+
+## end   gnulib module getdtablesize
+
 ## begin gnulib module getgroups
 
 if gl_GNULIB_ENABLED_getgroups
@@ -568,6 +588,12 @@
 
 ## end   gnulib module pathmax
 
+## begin gnulib module pipe2
+
+libgnu_a_SOURCES += pipe2.c
+
+## end   gnulib module pipe2
+
 ## begin gnulib module pselect
 
 
@@ -1704,9 +1730,7 @@
 
 ## begin gnulib module verify
 
-if gl_GNULIB_ENABLED_verify
 
-endif
 EXTRA_DIST += verify.h
 
 ## end   gnulib module verify

=== added file 'lib/pipe2.c'
--- lib/pipe2.c	1970-01-01 00:00:00 +0000
+++ lib/pipe2.c	2013-07-06 07:04:07 +0000
@@ -0,0 +1,171 @@
+/* Create a pipe, with specific opening flags.
+   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <unistd.h>
+
+#include <errno.h>
+#include <fcntl.h>
+
+#if GNULIB_BINARY_IO
+# include "binary-io.h"
+#endif
+
+#include "verify.h"
+
+#if GNULIB_defined_O_NONBLOCK
+# include "nonblocking.h"
+#endif
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Native Windows API.  */
+
+# include <io.h>
+
+#endif
+
+int
+pipe2 (int fd[2], int flags)
+{
+  /* Mingw _pipe() corrupts fd on failure; also, if we succeed at
+     creating the pipe but later fail at changing fcntl, we want
+     to leave fd unchanged: http://austingroupbugs.net/view.php?id=467  */
+  int tmp[2];
+  tmp[0] = fd[0];
+  tmp[1] = fd[1];
+
+#if HAVE_PIPE2
+# undef pipe2
+  /* Try the system call first, if it exists.  (We may be running with a glibc
+     that has the function but with an older kernel that lacks it.)  */
+  {
+    /* Cache the information whether the system call really exists.  */
+    static int have_pipe2_really; /* 0 = unknown, 1 = yes, -1 = no */
+    if (have_pipe2_really >= 0)
+      {
+        int result = pipe2 (fd, flags);
+        if (!(result < 0 && errno == ENOSYS))
+          {
+            have_pipe2_really = 1;
+            return result;
+          }
+        have_pipe2_really = -1;
+      }
+  }
+#endif
+
+  /* Check the supported flags.  */
+  if ((flags & ~(O_CLOEXEC | O_NONBLOCK | O_BINARY | O_TEXT)) != 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Native Windows API.  */
+
+  if (_pipe (fd, 4096, flags & ~O_NONBLOCK) < 0)
+    {
+      fd[0] = tmp[0];
+      fd[1] = tmp[1];
+      return -1;
+    }
+
+  /* O_NONBLOCK handling.
+     On native Windows platforms, O_NONBLOCK is defined by gnulib.  Use the
+     functions defined by the gnulib module 'nonblocking'.  */
+# if GNULIB_defined_O_NONBLOCK
+  if (flags & O_NONBLOCK)
+    {
+      if (set_nonblocking_flag (fd[0], true) != 0
+          || set_nonblocking_flag (fd[1], true) != 0)
+        goto fail;
+    }
+# else
+  {
+    verify (O_NONBLOCK == 0);
+  }
+# endif
+
+  return 0;
+
+#else
+/* Unix API.  */
+
+  if (pipe (fd) < 0)
+    return -1;
+
+  /* POSIX <http://www.opengroup.org/onlinepubs/9699919799/functions/pipe.html>
+     says that initially, the O_NONBLOCK and FD_CLOEXEC flags are cleared on
+     both fd[0] and fd[1].  */
+
+  /* O_NONBLOCK handling.
+     On Unix platforms, O_NONBLOCK is defined by the system.  Use fcntl().  */
+  if (flags & O_NONBLOCK)
+    {
+      int fcntl_flags;
+
+      if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0
+          || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1
+          || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0
+          || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1)
+        goto fail;
+    }
+
+  if (flags & O_CLOEXEC)
+    {
+      int fcntl_flags;
+
+      if ((fcntl_flags = fcntl (fd[1], F_GETFD, 0)) < 0
+          || fcntl (fd[1], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1
+          || (fcntl_flags = fcntl (fd[0], F_GETFD, 0)) < 0
+          || fcntl (fd[0], F_SETFD, fcntl_flags | FD_CLOEXEC) == -1)
+        goto fail;
+    }
+
+# if O_BINARY
+  if (flags & O_BINARY)
+    {
+      setmode (fd[1], O_BINARY);
+      setmode (fd[0], O_BINARY);
+    }
+  else if (flags & O_TEXT)
+    {
+      setmode (fd[1], O_TEXT);
+      setmode (fd[0], O_TEXT);
+    }
+# endif
+
+  return 0;
+
+#endif
+
+#if GNULIB_defined_O_NONBLOCK || \
+  !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
+ fail:
+  {
+    int saved_errno = errno;
+    close (fd[0]);
+    close (fd[1]);
+    fd[0] = tmp[0];
+    fd[1] = tmp[1];
+    errno = saved_errno;
+    return -1;
+  }
+#endif
+}

=== added file 'm4/fcntl.m4'
--- m4/fcntl.m4	1970-01-01 00:00:00 +0000
+++ m4/fcntl.m4	2013-07-06 07:04:07 +0000
@@ -0,0 +1,95 @@
+# fcntl.m4 serial 5
+dnl Copyright (C) 2009-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# For now, this module ensures that fcntl()
+# - supports F_DUPFD correctly
+# - supports or emulates F_DUPFD_CLOEXEC
+# - supports F_GETFD
+# Still to be ported to mingw:
+# - F_SETFD
+# - F_GETFL, F_SETFL
+# - F_GETOWN, F_SETOWN
+# - F_GETLK, F_SETLK, F_SETLKW
+AC_DEFUN([gl_FUNC_FCNTL],
+[
+  dnl Persuade glibc to expose F_DUPFD_CLOEXEC.
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_CHECK_FUNCS_ONCE([fcntl])
+  if test $ac_cv_func_fcntl = no; then
+    gl_REPLACE_FCNTL
+  else
+    dnl cygwin 1.5.x F_DUPFD has wrong errno, and allows negative target
+    dnl haiku alpha 2 F_DUPFD has wrong errno
+    AC_CACHE_CHECK([whether fcntl handles F_DUPFD correctly],
+      [gl_cv_func_fcntl_f_dupfd_works],
+      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <fcntl.h>
+#include <errno.h>
+]], [[int result = 0;
+      if (fcntl (0, F_DUPFD, -1) != -1) result |= 1;
+      if (errno != EINVAL) result |= 2;
+      return result;
+         ]])],
+         [gl_cv_func_fcntl_f_dupfd_works=yes],
+         [gl_cv_func_fcntl_f_dupfd_works=no],
+         [# Guess that it works on glibc systems
+          case $host_os in #((
+            *-gnu*) gl_cv_func_fcntl_f_dupfd_works="guessing yes";;
+            *)      gl_cv_func_fcntl_f_dupfd_works="guessing no";;
+          esac])])
+    case $gl_cv_func_fcntl_f_dupfd_works in
+      *yes) ;;
+      *) gl_REPLACE_FCNTL
+        AC_DEFINE([FCNTL_DUPFD_BUGGY], [1], [Define this to 1 if F_DUPFD
+          behavior does not match POSIX]) ;;
+    esac
+
+    dnl Many systems lack F_DUPFD_CLOEXEC
+    AC_CACHE_CHECK([whether fcntl understands F_DUPFD_CLOEXEC],
+      [gl_cv_func_fcntl_f_dupfd_cloexec],
+      [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <fcntl.h>
+#ifndef F_DUPFD_CLOEXEC
+choke me
+#endif
+         ]])],
+         [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#ifdef __linux__
+/* The Linux kernel only added F_DUPFD_CLOEXEC in 2.6.24, so we always replace
+   it to support the semantics on older kernels that failed with EINVAL.  */
+choke me
+#endif
+           ]])],
+           [gl_cv_func_fcntl_f_dupfd_cloexec=yes],
+           [gl_cv_func_fcntl_f_dupfd_cloexec="needs runtime check"])],
+         [gl_cv_func_fcntl_f_dupfd_cloexec=no])])
+    if test "$gl_cv_func_fcntl_f_dupfd_cloexec" != yes; then
+      gl_REPLACE_FCNTL
+      dnl No witness macro needed for this bug.
+    fi
+  fi
+  dnl Replace fcntl() for supporting the gnulib-defined fchdir() function,
+  dnl to keep fchdir's bookkeeping up-to-date.
+  m4_ifdef([gl_FUNC_FCHDIR], [
+    gl_TEST_FCHDIR
+    if test $HAVE_FCHDIR = 0; then
+      gl_REPLACE_FCNTL
+    fi
+  ])
+])
+
+AC_DEFUN([gl_REPLACE_FCNTL],
+[
+  AC_REQUIRE([gl_FCNTL_H_DEFAULTS])
+  AC_CHECK_FUNCS_ONCE([fcntl])
+  if test $ac_cv_func_fcntl = no; then
+    HAVE_FCNTL=0
+  else
+    REPLACE_FCNTL=1
+  fi
+])

=== added file 'm4/getdtablesize.m4'
--- m4/getdtablesize.m4	1970-01-01 00:00:00 +0000
+++ m4/getdtablesize.m4	2013-07-06 07:04:07 +0000
@@ -0,0 +1,17 @@
+# getdtablesize.m4 serial 4
+dnl Copyright (C) 2008-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_GETDTABLESIZE],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_CHECK_FUNCS_ONCE([getdtablesize])
+  if test $ac_cv_func_getdtablesize != yes; then
+    HAVE_GETDTABLESIZE=0
+  fi
+])
+
+# Prerequisites of lib/getdtablesize.c.
+AC_DEFUN([gl_PREREQ_GETDTABLESIZE], [:])

=== modified file 'm4/gnulib-comp.m4'
--- m4/gnulib-comp.m4	2013-05-07 21:34:03 +0000
+++ m4/gnulib-comp.m4	2013-07-06 07:04:07 +0000
@@ -63,6 +63,7 @@
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   # Code from module extern-inline:
   # Code from module faccessat:
+  # Code from module fcntl:
   # Code from module fcntl-h:
   # Code from module fdatasync:
   # Code from module fdopendir:
@@ -70,6 +71,7 @@
   # Code from module fpending:
   # Code from module fstatat:
   # Code from module fsync:
+  # Code from module getdtablesize:
   # Code from module getgroups:
   # Code from module getloadavg:
   # Code from module getopt-gnu:
@@ -92,6 +94,7 @@
   # Code from module nocrash:
   # Code from module openat-h:
   # Code from module pathmax:
+  # Code from module pipe2:
   # Code from module pselect:
   # Code from module pthread_sigmask:
   # Code from module putenv:
@@ -191,6 +194,11 @@
   fi
   gl_MODULE_INDICATOR([faccessat])
   gl_UNISTD_MODULE_INDICATOR([faccessat])
+  gl_FUNC_FCNTL
+  if test $HAVE_FCNTL = 0 || test $REPLACE_FCNTL = 1; then
+    AC_LIBOBJ([fcntl])
+  fi
+  gl_FCNTL_MODULE_INDICATOR([fcntl])
   gl_FCNTL_H
   gl_FUNC_FDATASYNC
   if test $HAVE_FDATASYNC = 0; then
@@ -273,6 +281,8 @@
   fi
   gl_TIME_MODULE_INDICATOR([mktime])
   gl_MULTIARCH
+  gl_FUNC_PIPE2
+  gl_UNISTD_MODULE_INDICATOR([pipe2])
   gl_FUNC_PSELECT
   if test $HAVE_PSELECT = 0 || test $REPLACE_PSELECT = 1; then
     AC_LIBOBJ([pselect])
@@ -364,6 +374,7 @@
   gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b=false
   gl_gnulib_enabled_dosname=false
   gl_gnulib_enabled_euidaccess=false
+  gl_gnulib_enabled_getdtablesize=false
   gl_gnulib_enabled_getgroups=false
   gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false
   gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1=false
@@ -373,7 +384,6 @@
   gl_gnulib_enabled_stat=false
   gl_gnulib_enabled_strtoll=false
   gl_gnulib_enabled_strtoull=false
-  gl_gnulib_enabled_verify=false
   gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec=false
   func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b ()
   {
@@ -407,6 +417,18 @@
       fi
     fi
   }
+  func_gl_gnulib_m4code_getdtablesize ()
+  {
+    if ! $gl_gnulib_enabled_getdtablesize; then
+      gl_FUNC_GETDTABLESIZE
+      if test $HAVE_GETDTABLESIZE = 0; then
+        AC_LIBOBJ([getdtablesize])
+        gl_PREREQ_GETDTABLESIZE
+      fi
+      gl_UNISTD_MODULE_INDICATOR([getdtablesize])
+      gl_gnulib_enabled_getdtablesize=true
+    fi
+  }
   func_gl_gnulib_m4code_getgroups ()
   {
     if ! $gl_gnulib_enabled_getgroups; then
@@ -479,9 +501,6 @@
       if test $REPLACE_STAT = 1; then
         func_gl_gnulib_m4code_pathmax
       fi
-      if test $REPLACE_STAT = 1; then
-        func_gl_gnulib_m4code_verify
-      fi
     fi
   }
   func_gl_gnulib_m4code_strtoll ()
@@ -508,12 +527,6 @@
       gl_gnulib_enabled_strtoull=true
     fi
   }
-  func_gl_gnulib_m4code_verify ()
-  {
-    if ! $gl_gnulib_enabled_verify; then
-      gl_gnulib_enabled_verify=true
-    fi
-  }
   func_gl_gnulib_m4code_682e609604ccaac6be382e4ee3a4eaec ()
   {
     if ! $gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec; then
@@ -532,6 +545,9 @@
   if test $HAVE_FACCESSAT = 0; then
     func_gl_gnulib_m4code_03e0aaad4cb89ca757653bd367a6ccb7
   fi
+  if test $HAVE_FCNTL = 0 || test $REPLACE_FCNTL = 1; then
+    func_gl_gnulib_m4code_getdtablesize
+  fi
   if test $HAVE_FDOPENDIR = 0; then
     func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
   fi
@@ -568,19 +584,14 @@
   if { test $HAVE_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; } && test $ac_cv_type_long_long_int = yes; then
     func_gl_gnulib_m4code_strtoll
   fi
-  if test $HAVE_STRTOIMAX = 0 || test $REPLACE_STRTOIMAX = 1; then
-    func_gl_gnulib_m4code_verify
-  fi
   if test $ac_cv_func_strtoumax = no && test $ac_cv_type_unsigned_long_long_int = yes; then
     func_gl_gnulib_m4code_strtoull
   fi
-  if test $ac_cv_func_strtoumax = no; then
-    func_gl_gnulib_m4code_verify
-  fi
   m4_pattern_allow([^gl_GNULIB_ENABLED_])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b], [$gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_dosname], [$gl_gnulib_enabled_dosname])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_euidaccess], [$gl_gnulib_enabled_euidaccess])
+  AM_CONDITIONAL([gl_GNULIB_ENABLED_getdtablesize], [$gl_gnulib_enabled_getdtablesize])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_getgroups], [$gl_gnulib_enabled_getgroups])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36], [$gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1], [$gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1])
@@ -590,7 +601,6 @@
   AM_CONDITIONAL([gl_GNULIB_ENABLED_stat], [$gl_gnulib_enabled_stat])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoll], [$gl_gnulib_enabled_strtoll])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_strtoull], [$gl_gnulib_enabled_strtoull])
-  AM_CONDITIONAL([gl_GNULIB_ENABLED_verify], [$gl_gnulib_enabled_verify])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec], [$gl_gnulib_enabled_682e609604ccaac6be382e4ee3a4eaec])
   # End of code from modules
   m4_ifval(gl_LIBSOURCES_LIST, [
@@ -764,6 +774,7 @@
   lib/execinfo.c
   lib/execinfo.in.h
   lib/faccessat.c
+  lib/fcntl.c
   lib/fcntl.in.h
   lib/fdatasync.c
   lib/fdopendir.c
@@ -776,6 +787,7 @@
   lib/fsync.c
   lib/ftoastr.c
   lib/ftoastr.h
+  lib/getdtablesize.c
   lib/getgroups.c
   lib/getloadavg.c
   lib/getopt.c
@@ -799,6 +811,7 @@
   lib/openat-proc.c
   lib/openat.h
   lib/pathmax.h
+  lib/pipe2.c
   lib/pselect.c
   lib/pthread_sigmask.c
   lib/putenv.c
@@ -870,6 +883,7 @@
   m4/extern-inline.m4
   m4/faccessat.m4
   m4/fcntl-o.m4
+  m4/fcntl.m4
   m4/fcntl_h.m4
   m4/fdatasync.m4
   m4/fdopendir.m4
@@ -877,6 +891,7 @@
   m4/fpending.m4
   m4/fstatat.m4
   m4/fsync.m4
+  m4/getdtablesize.m4
   m4/getgroups.m4
   m4/getloadavg.m4
   m4/getopt.m4
@@ -897,6 +912,7 @@
   m4/nocrash.m4
   m4/off_t.m4
   m4/pathmax.m4
+  m4/pipe2.m4
   m4/pselect.m4
   m4/pthread_sigmask.m4
   m4/putenv.m4

=== added file 'm4/pipe2.m4'
--- m4/pipe2.m4	1970-01-01 00:00:00 +0000
+++ m4/pipe2.m4	2013-07-06 07:04:07 +0000
@@ -0,0 +1,18 @@
+# pipe2.m4 serial 2
+dnl Copyright (C) 2009-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_PIPE2],
+[
+  AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+
+  dnl Persuade glibc <unistd.h> to declare pipe2().
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+  AC_CHECK_FUNCS_ONCE([pipe2])
+  if test $ac_cv_func_pipe2 != yes; then
+    HAVE_PIPE2=0
+  fi
+])

=== modified file 'nt/ChangeLog'
--- nt/ChangeLog	2013-06-25 15:08:47 +0000
+++ nt/ChangeLog	2013-07-06 08:25:40 +0000
@@ -1,3 +1,9 @@
+2013-07-06  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Make file descriptors close-on-exec when possible.
+	* gnulib.mk: Remove empty gl_GNULIB_ENABLED_verify section;
+	otherwise, gnulib-tool complains given close-on-exec changes.
+
 2013-06-25  Juanma Barranquero  <lekktu <at> gmail.com>
 
 	* configure.bat: Add warning to the help text about using the

=== modified file 'nt/gnulib.mk'
--- nt/gnulib.mk	2013-05-16 05:51:39 +0000
+++ nt/gnulib.mk	2013-07-06 07:04:07 +0000
@@ -876,9 +876,6 @@
 
 ## begin gnulib module verify
 
-if gl_GNULIB_ENABLED_verify
-
-endif
 EXTRA_DIST += verify.h
 
 ## end   gnulib module verify

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2013-07-06 08:26:18 +0000
+++ src/ChangeLog	2013-07-06 08:57:16 +0000
@@ -1,3 +1,39 @@
+2013-07-06  Paul Eggert  <eggert <at> cs.ucla.edu>
+
+	Make file descriptors close-on-exec when possible.
+	This simplifies Emacs a bit, since it no longer needs to worry
+	about closing file descriptors by hand in some cases.
+	It also fixes some unlikely races.  Not all such races, as
+	libraries often open files internally without setting
+	close-on-exec, but it's an improvement.
+	* alloc.c (valid_pointer_p) [!WINDOWSNT]:
+	* callproc.c (Fcall_process) [!MSDOS]:
+	* emacs.c (main) [!DOS_NT]:
+	* nsterm.m (ns_term_init):
+	* process.c (create_process):
+	Use 'pipe2' with O_CLOEXEC instead of 'pipe'.
+	* emacs.c (Fcall_process_region) [HAVE_MKOSTEMP]:
+	* filelock.c (create_lock_file) [HAVE_MKOSTEMP]:
+	Prefer mkostemp with O_CLOEXEC to mkstemp.
+	* callproc.c (relocate_fd) [!WINDOWSNT]:
+	* emacs.c (main): Use F_DUPFD_CLOEXEC, not plain F_DUPFD.
+	No need to use fcntl (..., F_SETFD, FD_CLOEXEC), since we're
+	now using pipe2.
+	* filelock.c (create_lock_file) [! HAVE_MKOSTEMP]:
+	Make the resulting file descriptor close-on-exec.
+	* lisp.h, lread.c, process.c (close_load_descs, close_process_descs):
+	* lread.c (load_descriptor_list, load_descriptor_unwind):
+	Remove; no longer needed.  All uses removed.
+	* process.c (SOCK_CLOEXEC): Define to 0 if not supplied by system.
+	(close_on_exec, accept4, process_socket) [!SOCK_CLOEXEC]:
+	New functions.
+	(socket) [!SOCK_CLOEXEC]: Supply a substitute.
+	(Fmake_network_process, Fnetwork_interface_list):
+	(Fnetwork_interface_info, server_accept_connection):
+	Make newly-created socket close-on-exec.
+	* sysdep.c (emacs_open, emacs_fopen):
+	Make new-created descriptor close-on-exec.
+
 2013-07-06  Eli Zaretskii  <eliz <at> gnu.org>
 
 	* data.c (Fmultibyte_string_p): Doc fix.

=== modified file 'src/alloc.c'
--- src/alloc.c	2013-07-05 16:58:01 +0000
+++ src/alloc.c	2013-07-06 07:04:07 +0000
@@ -4741,7 +4741,7 @@
      Unfortunately, we cannot use NULL_DEVICE here, as emacs_write may
      not validate p in that case.  */
 
-  if (pipe (fd) == 0)
+  if (pipe2 (fd, O_CLOEXEC) == 0)
     {
       bool valid = emacs_write (fd[1], (char *) p, 16) == 16;
       emacs_close (fd[1]);

=== modified file 'src/callproc.c'
--- src/callproc.c	2013-07-06 07:02:40 +0000
+++ src/callproc.c	2013-07-06 07:05:58 +0000
@@ -517,7 +517,7 @@
     {
 #ifndef MSDOS
       int fd[2];
-      if (pipe (fd) == -1)
+      if (pipe2 (fd, O_CLOEXEC) != 0)
 	{
 	  int pipe_errno = errno;
 	  emacs_close (filefd);
@@ -1034,12 +1034,16 @@
     memcpy (tempfile, SDATA (encoded_tem), SBYTES (encoded_tem) + 1);
     coding_systems = Qt;
 
-#ifdef HAVE_MKSTEMP
+#if defined HAVE_MKOSTEMP || defined HAVE_MKSTEMP
     {
       int fd;
 
       block_input ();
+# ifdef HAVE_MKOSTEMP
+      fd = mkostemp (tempfile, O_CLOEXEC);
+# else
       fd = mkstemp (tempfile);
+# endif
       unblock_input ();
       if (fd == -1)
 	report_file_error ("Failed to open temporary file",
@@ -1182,15 +1186,6 @@
 
   pid_t pid = getpid ();
 
-  /* Close Emacs's descriptors that this process should not have.  */
-  close_process_descs ();
-
-  /* DOS_NT isn't in a vfork, so if we are in the middle of load-file,
-     we will lose if we call close_load_descs here.  */
-#ifndef DOS_NT
-  close_load_descs ();
-#endif
-
   /* Note that use of alloca is always safe here.  It's obvious for systems
      that do not have true vfork or that have true (stack) alloca.
      If using vfork and C_ALLOCA (when Emacs used to include
@@ -1352,9 +1347,11 @@
   emacs_close (1);
   emacs_close (2);
 
+  /* Redirect file descriptors and clear FD_CLOEXEC on the redirected ones.  */
   dup2 (in, 0);
   dup2 (out, 1);
   dup2 (err, 2);
+
   emacs_close (in);
   if (out != in)
     emacs_close (out);
@@ -1392,7 +1389,7 @@
     return fd;
   else
     {
-      int new = fcntl (fd, F_DUPFD, minfd);
+      int new = fcntl (fd, F_DUPFD_CLOEXEC, minfd);
       if (new == -1)
 	{
 	  const char *message_1 = "Error while setting up child: ";

=== modified file 'src/emacs.c'
--- src/emacs.c	2013-07-06 07:02:40 +0000
+++ src/emacs.c	2013-07-06 07:05:58 +0000
@@ -889,7 +889,7 @@
 	  emacs_close (0);
 	  emacs_close (1);
 	  result = emacs_open (term, O_RDWR, 0);
-	  if (result < 0 || dup (0) < 0)
+	  if (result < 0 || fcntl (0, F_DUPFD_CLOEXEC, 1) < 0)
 	    {
 	      char *errstring = strerror (errno);
 	      fprintf (stderr, "%s: %s: %s\n", argv[0], term, errstring);
@@ -969,7 +969,7 @@
 	 use a pipe for synchronization.  The parent waits for the child
 	 to close its end of the pipe (using `daemon-initialized')
 	 before exiting.  */
-      if (pipe (daemon_pipe) == -1)
+      if (pipe2 (daemon_pipe, O_CLOEXEC) != 0)
 	{
 	  fprintf (stderr, "Cannot pipe!\n");
 	  exit (1);
@@ -1065,9 +1065,6 @@
        	daemon_name = xstrdup (dname_arg);
       /* Close unused reading end of the pipe.  */
       close (daemon_pipe[0]);
-      /* Make sure that the used end of the pipe is closed on exec, so
-	 that it is not accessible to programs started from .emacs.  */
-      fcntl (daemon_pipe[1], F_SETFD, FD_CLOEXEC);
 
       setsid ();
 #else /* DOS_NT */

=== modified file 'src/filelock.c'
--- src/filelock.c	2013-05-05 00:51:49 +0000
+++ src/filelock.c	2013-07-06 07:04:07 +0000
@@ -416,8 +416,13 @@
       memcpy (nonce, lfname, lfdirlen);
       strcpy (nonce + lfdirlen, nonce_base);
 
-#if HAVE_MKSTEMP
-      /* Prefer mkstemp if available, as it avoids a race between
+#if HAVE_MKOSTEMP
+      /* Prefer mkostemp to mkstemp, as it avoids a window where FD is
+	 temporarily open without close-on-exec.  */
+      fd = mkostemp (nonce, O_BINARY | O_CLOEXEC);
+      need_fchmod = 1;
+#elif HAVE_MKSTEMP
+      /* Prefer mkstemp to mktemp, as it avoids a race between
 	 mktemp and emacs_open.  */
       fd = mkstemp (nonce);
       need_fchmod = 1;
@@ -432,7 +437,11 @@
 	err = errno;
       else
 	{
-	  ptrdiff_t lock_info_len = strlen (lock_info_str);
+	  ptrdiff_t lock_info_len;
+#if ! HAVE_MKOSTEMP
+	  fcntl (fd, F_SETFD, FD_CLOEXEC);
+#endif
+	  lock_info_len = strlen (lock_info_str);
 	  err = 0;
 	  if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
 	      || (need_fchmod && fchmod (fd, world_readable) != 0))

=== modified file 'src/lisp.h'
--- src/lisp.h	2013-07-04 09:29:28 +0000
+++ src/lisp.h	2013-07-06 07:04:07 +0000
@@ -3668,7 +3668,6 @@
 extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
                          Lisp_Object);
 extern void dir_warning (const char *, Lisp_Object);
-extern void close_load_descs (void);
 extern void init_obarray (void);
 extern void init_lread (void);
 extern void syms_of_lread (void);
@@ -3995,7 +3994,6 @@
 extern void add_gpm_wait_descriptor (int);
 extern void delete_gpm_wait_descriptor (int);
 #endif
-extern void close_process_descs (void);
 extern void init_process_emacs (void);
 extern void syms_of_process (void);
 extern void setup_process_coding_systems (Lisp_Object);

=== modified file 'src/lread.c'
--- src/lread.c	2013-07-06 07:02:40 +0000
+++ src/lread.c	2013-07-06 07:05:58 +0000
@@ -95,9 +95,6 @@
    It must be set to nil before all top-level calls to read0.  */
 static Lisp_Object read_objects;
 
-/* List of descriptors now open for Fload.  */
-static Lisp_Object load_descriptor_list;
-
 /* File for get_file_char to read from.  Use by load.  */
 static FILE *instream;
 
@@ -149,7 +146,6 @@
                           Lisp_Object, Lisp_Object,
                           Lisp_Object, Lisp_Object);
 static Lisp_Object load_unwind (Lisp_Object);
-static Lisp_Object load_descriptor_unwind (Lisp_Object);
 
 /* Functions that read one byte from the current source READCHARFUN
    or unreads one byte.  If the integer argument C is -1, it returns
@@ -1328,11 +1324,8 @@
     }
 
   record_unwind_protect (load_unwind, make_save_pointer (stream));
-  record_unwind_protect (load_descriptor_unwind, load_descriptor_list);
   specbind (Qload_file_name, found);
   specbind (Qinhibit_file_name_operation, Qnil);
-  load_descriptor_list
-    = Fcons (make_number (fileno (stream)), load_descriptor_list);
   specbind (Qload_in_progress, Qt);
 
   instream = stream;
@@ -1395,26 +1388,6 @@
     }
   return Qnil;
 }
-
-static Lisp_Object
-load_descriptor_unwind (Lisp_Object oldlist)
-{
-  load_descriptor_list = oldlist;
-  return Qnil;
-}
-
-/* Close all descriptors in use for Floads.
-   This is used when starting a subprocess.  */
-
-void
-close_load_descs (void)
-{
-#ifndef WINDOWSNT
-  Lisp_Object tail;
-  for (tail = load_descriptor_list; CONSP (tail); tail = XCDR (tail))
-    emacs_close (XFASTINT (XCAR (tail)));
-#endif
-}
 
 static bool
 complete_filename_p (Lisp_Object pathname)
@@ -4349,9 +4322,6 @@
 
   load_in_progress = 0;
   Vload_file_name = Qnil;
-
-  load_descriptor_list = Qnil;
-
   Vstandard_input = Qt;
   Vloads_in_progress = Qnil;
 }
@@ -4624,9 +4594,6 @@
 
   /* Vsource_directory was initialized in init_lread.  */
 
-  load_descriptor_list = Qnil;
-  staticpro (&load_descriptor_list);
-
   DEFSYM (Qcurrent_load_list, "current-load-list");
   DEFSYM (Qstandard_input, "standard-input");
   DEFSYM (Qread_char, "read-char");

=== modified file 'src/nsterm.m'
--- src/nsterm.m	2013-06-27 14:47:52 +0000
+++ src/nsterm.m	2013-07-06 07:04:07 +0000
@@ -4142,7 +4142,7 @@
 
   if (selfds[0] == -1)
     {
-      if (pipe (selfds) == -1)
+      if (pipe2 (selfds, O_CLOEXEC) != 0)
         {
           fprintf (stderr, "Failed to create pipe: %s\n",
                    emacs_strerror (errno));

=== modified file 'src/process.c'
--- src/process.c	2013-07-05 16:58:01 +0000
+++ src/process.c	2013-07-06 09:07:02 +0000
@@ -135,6 +135,34 @@
 		       EMACS_TIME *, void *);
 #endif
 
+#ifndef SOCK_CLOEXEC
+# define SOCK_CLOEXEC 0
+
+/* Emulate GNU/Linux accept4 and socket well enough for this module.  */
+
+static int
+close_on_exec (int fd)
+{
+  if (0 <= fd)
+    fcntl (fd, F_SETFD, FD_CLOEXEC);
+  return fd;
+}
+
+static int
+accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
+{
+  return close_on_exec (accept (sockfd, addr, addrlen));
+}
+
+static int
+process_socket (int domain, int type, int protocol)
+{
+  return close_on_exec (socket (domain, type, protocol));
+}
+# undef socket
+# define socket(domain, type, protocol) process_socket (domain, type, protocol)
+#endif
+
 /* Work around GCC 4.7.0 bug with strict overflow checking; see
    <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
    These lines can be removed once the GCC bug is fixed.  */
@@ -1619,14 +1647,11 @@
   else
 #endif /* HAVE_PTYS */
     {
-      int tem;
-      tem = pipe (sv);
-      if (tem < 0)
+      if (pipe2 (sv, O_CLOEXEC) != 0)
 	report_file_error ("Creating pipe", Qnil);
       inchannel = sv[0];
       forkout = sv[1];
-      tem = pipe (sv);
-      if (tem < 0)
+      if (pipe2 (sv, O_CLOEXEC) != 0)
 	{
 	  emacs_close (inchannel);
 	  emacs_close (forkout);
@@ -1637,29 +1662,14 @@
     }
 
 #ifndef WINDOWSNT
-    {
-      int tem;
-
-      tem = pipe (wait_child_setup);
-      if (tem < 0)
-	report_file_error ("Creating pipe", Qnil);
-      tem = fcntl (wait_child_setup[1], F_GETFD, 0);
-      if (tem >= 0)
-	tem = fcntl (wait_child_setup[1], F_SETFD, tem | FD_CLOEXEC);
-      if (tem < 0)
-	{
-	  emacs_close (wait_child_setup[0]);
-	  emacs_close (wait_child_setup[1]);
-	  report_file_error ("Setting file descriptor flags", Qnil);
-	}
-    }
+  if (pipe2 (wait_child_setup, O_CLOEXEC) != 0)
+    report_file_error ("Creating pipe", Qnil);
 #endif
 
   fcntl (inchannel, F_SETFL, O_NONBLOCK);
   fcntl (outchannel, F_SETFL, O_NONBLOCK);
 
-  /* Record this as an active process, with its channels.
-     As a result, child_setup will close Emacs's side of the pipes.  */
+  /* Record this as an active process, with its channels.  */
   chan_process[inchannel] = process;
   XPROCESS (process)->infd = inchannel;
   XPROCESS (process)->outfd = outchannel;
@@ -3135,7 +3145,8 @@
     retry_connect:
 #endif
 
-      s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol);
+      s = socket (lres->ai_family, lres->ai_socktype | SOCK_CLOEXEC,
+		  lres->ai_protocol);
       if (s < 0)
 	{
 	  xerrno = errno;
@@ -3532,7 +3543,7 @@
   int s;
   Lisp_Object res;
 
-  s = socket (AF_INET, SOCK_STREAM, 0);
+  s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
   if (s < 0)
     return Qnil;
 
@@ -3688,7 +3699,7 @@
     error ("interface name too long");
   strcpy (rq.ifr_name, SSDATA (ifname));
 
-  s = socket (AF_INET, SOCK_STREAM, 0);
+  s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
   if (s < 0)
     return Qnil;
 
@@ -3984,7 +3995,7 @@
   } saddr;
   socklen_t len = sizeof saddr;
 
-  s = accept (channel, &saddr.sa, &len);
+  s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC);
 
   if (s < 0)
     {
@@ -6858,32 +6869,6 @@
 #endif
 }
 
-/* Close all descriptors currently in use for communication
-   with subprocess.  This is used in a newly-forked subprocess
-   to get rid of irrelevant descriptors.  */
-
-void
-close_process_descs (void)
-{
-#ifndef DOS_NT
-  int i;
-  for (i = 0; i < MAXDESC; i++)
-    {
-      Lisp_Object process;
-      process = chan_process[i];
-      if (!NILP (process))
-	{
-	  int in  = XPROCESS (process)->infd;
-	  int out = XPROCESS (process)->outfd;
-	  if (in >= 0)
-	    emacs_close (in);
-	  if (out >= 0 && in != out)
-	    emacs_close (out);
-	}
-    }
-#endif
-}
-
 DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
        doc: /* Return the (or a) process associated with BUFFER.
 BUFFER may be a buffer or the name of one.  */)

=== modified file 'src/sysdep.c'
--- src/sysdep.c	2013-07-06 07:02:40 +0000
+++ src/sysdep.c	2013-07-06 07:05:58 +0000
@@ -543,8 +543,6 @@
 #endif
 	}
 
-      close_process_descs ();	/* Close Emacs's pipes/ptys */
-
 #ifdef MSDOS    /* Demacs 1.1.2 91/10/20 Manabu Higashida */
       {
 	char *epwd = getenv ("PWD");
@@ -2152,6 +2150,8 @@
 #endif
 
 /* Open FILE for Emacs use, using open flags OFLAG and mode MODE.
+   Arrange for subprograms to not inherit the file descriptor.
+   Prefer a method that is multithread-safe, if available.
    Do not fail merely because the open was interrupted by a signal.
    Allow the user to quit.  */
 
@@ -2159,8 +2159,11 @@
 emacs_open (const char *file, int oflags, int mode)
 {
   int fd;
+  oflags |= O_CLOEXEC;
   while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
     QUIT;
+  if (! O_CLOEXEC && 0 <= fd)
+    fcntl (fd, F_SETFD, FD_CLOEXEC);
   return fd;
 }
 
@@ -2170,10 +2173,29 @@
 FILE *
 emacs_fopen (char const *file, char const *mode)
 {
-  FILE *fp;
-  while (! (fp = fopen (file, mode)) && errno == EINTR)
-    QUIT;
-  return fp;
+  int fd, omode, oflags;
+  int bflag = 0;
+  char const *m = mode;
+
+  switch (*m++)
+    {
+    case 'r': omode = O_RDONLY; oflags = 0; break;
+    case 'w': omode = O_WRONLY; oflags = O_CREAT | O_TRUNC; break;
+    case 'a': omode = O_WRONLY; oflags = O_CREAT | O_APPEND; break;
+    default: emacs_abort ();
+    }
+
+  while (*m)
+    switch (*m++)
+      {
+      case '+': omode = O_RDWR; break;
+      case 'b': bflag = O_BINARY; break;
+      case 't': bflag = O_TEXT; break;
+      default: /* Ignore.  */ break;
+      }
+
+  fd = emacs_open (file, omode | oflags | bflag, 0666);
+  return fd < 0 ? 0 : fdopen (fd, mode);
 }
 
 int





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14803; Package emacs. (Sat, 06 Jul 2013 11:33:02 GMT) Full text and rfc822 format available.

Message #8 received at 14803 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 14803 <at> debbugs.gnu.org
Subject: Re: bug#14803: Setting close-on-exec flag consistently
Date: Sat, 06 Jul 2013 14:31:30 +0300
> Date: Sat, 06 Jul 2013 02:13:19 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> 
> Tags: patch
> 
> Here's a patch I'd like to install into Emacs soon.
> It changes Emacs so that it creates file descriptors
> that are close-on-exec unless they are intended to
> be propagated to child processes.
> This patch may affect the Microsoft Windows ports
> so I'm sending it to bug-gnu-emacs first.
> Much of the new code is imported from gnulib.

Sorry, this won't fly.  The Windows build has its own implementations
of 'pipe' and 'socket' (because it needs to make them behave like
Posix APIs, and also because it needs to watch each subprocess and
each socket for the benefit of 'select', 'waitpid', SIGCHLD, etc.).
So the replacements from gnulib won't do.

Looking at the Emacs sources, I see that the Windows implementation of
'pipe' already makes it non-inheritable (see sys_pipe), so this
problem does not exist in the Windows build.

Socket handles _are_ inherited, but making them non-inheritable is not
easy (some say impossible in the general case), and since no one
complained till now, I'm willing to live with that until we hear some
real problems.

For mktemp/mkstemp in filelock.c, sys_open in w32.c already makes all
handles not inheritable by default, so that problem doesn't exist,
either.

As for emacs_open, it needs to use O_NOINHERIT instead of O_CLOEXEC
(or just use zero, since w32.c already adds the O_NOINHERIT flag in
sys_open).

So I think we should simply not compile lib/fcntl.c and lib/pipe2.c
(including their dependency modules) on MS-Windows.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14803; Package emacs. (Sat, 06 Jul 2013 17:19:02 GMT) Full text and rfc822 format available.

Message #11 received at 14803 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 14803 <at> debbugs.gnu.org
Subject: Re: bug#14803: Setting close-on-exec flag consistently
Date: Sat, 06 Jul 2013 10:18:07 -0700
On 07/06/2013 04:31 AM, Eli Zaretskii wrote:
> The Windows build has its own implementations
> of 'pipe' and 'socket' (because it needs to make them behave like
> Posix APIs, and also because it needs to watch each subprocess and
> each socket for the benefit of 'select', 'waitpid', SIGCHLD, etc.).
> So the replacements from gnulib won't do.

The gnulib replacements do that sort of thing too.  Emacs
uses a hybrid approach, which uses gnulib for some things
and its own (pre-gnulib) solution for others, and it should
be possible to keep the hybrid working in this case.  In the
long run it may be better to merge the two approaches rather
than maintain a hybrid, but that issue doesn't need to be
addressed now.

> Socket handles _are_ inherited, but making them non-inheritable is not
> easy (some say impossible in the general case), and since no one
> complained till now, I'm willing to live with that until we hear some
> real problems.

That's the intent of this patch.  On systems like w32 that
lack SOCK_CLOEXEC, the code creates sockets just as it did
before (using plain 'socket' and 'accept' rather than
'socket' and 'accept4' with SOCK_CLOEXEC).  The only
difference is that the proposed code then invokes
fcntl (fd, F_SETFD, FD_CLOEXEC) to set the close-on-exec
flag; this is needed on POSIXish systems that don't have
SOCK_CLOEXEC.  From what you say, on w32 platforms it's OK
if this is a no-op.  w32.c's fcntl currently returns
SOCKET_ERROR for this fcntl call, which should be fine,
since Emacs doesn't check for an error.

> For mktemp/mkstemp in filelock.c, sys_open in w32.c already makes all
> handles not inheritable by default, so that problem doesn't exist,
> either.

This should be OK, since the w32 port doesn't define
HAVE_MKOSTEMP, so Emacs should use mkstemp or mktemp as it
did before.  Emacs will now invoke fcntl (fd, F_SETFD,
FD_CLOEXEC) on the resulting file descriptor but that should
be OK as described above.

> As for emacs_open, it needs to use O_NOINHERIT instead of O_CLOEXEC
> (or just use zero, since w32.c already adds the O_NOINHERIT flag in
> sys_open).

The proposed patch does this, as fcntl.h should #define
O_CLOEXEC to O_NOINHERIT on w32.

> So I think we should simply not compile lib/fcntl.c and lib/pipe2.c
> (including their dependency modules) on MS-Windows.

That should be OK.  w32.c will need minor tweaks to support
F_DUPFD_CLOEXEC and pipe2, something along the following lines.

=== modified file 'nt/ChangeLog'
--- nt/ChangeLog	2013-07-06 09:44:23 +0000
+++ nt/ChangeLog	2013-07-06 16:55:23 +0000
@@ -3,6 +3,8 @@
 	Make file descriptors close-on-exec when possible (Bug#14803).
 	* gnulib.mk: Remove empty gl_GNULIB_ENABLED_verify section;
 	otherwise, gnulib-tool complains given close-on-exec changes.
+	* inc/ms-w32.h (pipe): Remove.
+	(pipe2): New macro.
 
 2013-06-25  Juanma Barranquero  <lekktu <at> gmail.com>
 

=== modified file 'nt/inc/ms-w32.h'
--- nt/inc/ms-w32.h	2013-05-15 17:06:26 +0000
+++ nt/inc/ms-w32.h	2013-07-06 16:55:23 +0000
@@ -211,7 +211,7 @@
 #define mktemp  sys_mktemp
 #undef open
 #define open    sys_open
-#define pipe    sys_pipe
+#define pipe2   sys_pipe2
 #undef read
 #define read    sys_read
 #define rename  sys_rename

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2013-07-06 16:37:12 +0000
+++ src/ChangeLog	2013-07-06 17:12:42 +0000
@@ -33,6 +33,8 @@
 	Make newly-created socket close-on-exec.
 	* sysdep.c (emacs_open, emacs_fopen):
 	Make new-created descriptor close-on-exec.
+	* w32.c (fcntl): Support F_DUPFD_CLOEXEC well enough for Emacs.
+	* w32.c, w32.h (sys_pipe2): Rename from 'pipe', with new flags arg.
 
 2013-07-06  Eli Zaretskii  <eliz <at> gnu.org>
 

=== modified file 'src/w32.c'
--- src/w32.c	2013-06-21 20:11:44 +0000
+++ src/w32.c	2013-07-06 17:12:42 +0000
@@ -6719,10 +6719,16 @@
 }
 
 /* Windows does not have an fcntl function.  Provide an implementation
-   solely for making sockets non-blocking.  */
+   good enough for Emacs.  */
 int
 fcntl (int s, int cmd, int options)
 {
+  /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
+     invoked in a context where fd1 is closed and all descriptors less
+     than fd1 are open, so sys_dup is an adequate implementation.  */
+  if (cmd == F_DUPFD_CLOEXEC)
+    return sys_dup (s);
+
   if (winsock_lib == NULL)
     {
       errno = ENETDOWN;
@@ -6864,13 +6870,14 @@
   return rc;
 }
 
-/* Unix pipe() has only one arg */
 int
-sys_pipe (int * phandles)
+sys_pipe2 (int * phandles, int pipe2_flags)
 {
   int rc;
   unsigned flags;
 
+  eassert (pipe2_flags == O_CLOEXEC);
+
   /* make pipe handles non-inheritable; when we spawn a child, we
      replace the relevant handle with an inheritable one.  Also put
      pipes into binary mode; we will do text mode translation ourselves

=== modified file 'src/w32.h'
--- src/w32.h	2013-03-05 22:35:41 +0000
+++ src/w32.h	2013-07-06 16:55:23 +0000
@@ -188,7 +188,7 @@
 
 extern int fchmod (int, mode_t);
 extern int sys_rename_replace (char const *, char const *, BOOL);
-extern int sys_pipe (int *);
+extern int sys_pipe2 (int *, int);
 
 extern void set_process_dir (char *);
 extern int sys_spawnve (int, char *, char **, char **);






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14803; Package emacs. (Sat, 06 Jul 2013 17:56:03 GMT) Full text and rfc822 format available.

Message #14 received at 14803 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 14803 <at> debbugs.gnu.org
Subject: Re: bug#14803: Setting close-on-exec flag consistently
Date: Sat, 06 Jul 2013 20:54:53 +0300
> Date: Sat, 06 Jul 2013 10:18:07 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: 14803 <at> debbugs.gnu.org
> 
> On 07/06/2013 04:31 AM, Eli Zaretskii wrote:
> > The Windows build has its own implementations
> > of 'pipe' and 'socket' (because it needs to make them behave like
> > Posix APIs, and also because it needs to watch each subprocess and
> > each socket for the benefit of 'select', 'waitpid', SIGCHLD, etc.).
> > So the replacements from gnulib won't do.
> 
> The gnulib replacements do that sort of thing too.  Emacs
> uses a hybrid approach, which uses gnulib for some things
> and its own (pre-gnulib) solution for others, and it should
> be possible to keep the hybrid working in this case.  In the
> long run it may be better to merge the two approaches rather
> than maintain a hybrid

I don't know how easy that would be, since the infrastructure used in
Emacs for this is very elaborate, and might contradict with
general-purpose use of gnulib.

> but that issue doesn't need to be addressed now.

Right.

> > Socket handles _are_ inherited, but making them non-inheritable is not
> > easy (some say impossible in the general case), and since no one
> > complained till now, I'm willing to live with that until we hear some
> > real problems.
> 
> That's the intent of this patch.  On systems like w32 that
> lack SOCK_CLOEXEC, the code creates sockets just as it did
> before (using plain 'socket' and 'accept' rather than
> 'socket' and 'accept4' with SOCK_CLOEXEC).

Given that w32 redirects calls to 'socket' to 'sys_socket', which is
implemented on w32.c, will the above still work?

> The only difference is that the proposed code then invokes fcntl
> (fd, F_SETFD, FD_CLOEXEC) to set the close-on-exec flag; this is
> needed on POSIXish systems that don't have SOCK_CLOEXEC.  From what
> you say, on w32 platforms it's OK if this is a no-op.  w32.c's fcntl
> currently returns SOCKET_ERROR for this fcntl call, which should be
> fine, since Emacs doesn't check for an error.
> 
> > For mktemp/mkstemp in filelock.c, sys_open in w32.c already makes all
> > handles not inheritable by default, so that problem doesn't exist,
> > either.
> 
> This should be OK, since the w32 port doesn't define
> HAVE_MKOSTEMP, so Emacs should use mkstemp or mktemp as it
> did before.  Emacs will now invoke fcntl (fd, F_SETFD,
> FD_CLOEXEC) on the resulting file descriptor but that should
> be OK as described above.
> 
> > As for emacs_open, it needs to use O_NOINHERIT instead of O_CLOEXEC
> > (or just use zero, since w32.c already adds the O_NOINHERIT flag in
> > sys_open).
> 
> The proposed patch does this, as fcntl.h should #define
> O_CLOEXEC to O_NOINHERIT on w32.
> 
> > So I think we should simply not compile lib/fcntl.c and lib/pipe2.c
> > (including their dependency modules) on MS-Windows.
> 
> That should be OK.  w32.c will need minor tweaks to support
> F_DUPFD_CLOEXEC and pipe2, something along the following lines.

I'm OK with the rest of your proposals.  I assume that lib/fcntl.c and
lib/pipe2.c will not be compiled for w32, due to some configure test?
Or did you have something else in mind?

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14803; Package emacs. (Sat, 06 Jul 2013 21:44:02 GMT) Full text and rfc822 format available.

Message #17 received at 14803 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 14803 <at> debbugs.gnu.org
Subject: Re: bug#14803: Setting close-on-exec flag consistently
Date: Sat, 06 Jul 2013 14:43:26 -0700
On 07/06/2013 10:54 AM, Eli Zaretskii wrote:
>> Date: Sat, 06 Jul 2013 10:18:07 -0700
>> From: Paul Eggert <eggert <at> cs.ucla.edu>
>> On systems like w32 that lack SOCK_CLOEXEC, the code creates
>> sockets just as it did before (using plain 'socket' and 'accept'
>> rather than 'socket' and 'accept4' with SOCK_CLOEXEC).
> 
> Given that w32 redirects calls to 'socket' to 'sys_socket', which is
> implemented on w32.c, will the above still work?

Yes, the idea is that it does the same calls as before,
to the same code in w32.c as before.

> I assume that lib/fcntl.c and
> lib/pipe2.c will not be compiled for w32, due to some configure test?

Yes, though that needs to be arranged.  The following further
patch should do it:

=== modified file 'ChangeLog'
--- ChangeLog	2013-07-06 09:44:23 +0000
+++ ChangeLog	2013-07-06 21:39:31 +0000
@@ -1,7 +1,9 @@
 2013-07-06  Paul Eggert  <eggert <at> cs.ucla.edu>
 
 	Make file descriptors close-on-exec when possible (Bug#14803).
-	* configure.ac (mkostemp): New function to check for.
+	* configure.ac (ac_cv_func_fcntl, gl_cv_func_fcntl_f_dupfd_cloexec)
+	(gl_cv_func_fcntl_f_dupfd_works, ac_cv_func_pipe2): Hotwire for MinGW.
+	(mkostemp): New function to check for.
 	(PTY_OPEN): Pass O_CLOEXEC to posix_openpt.
 	* lib/fcntl.c, lib/getdtablesize.c, lib/pipe2.c, m4/fcntl.m4:
 	* m4/getdtablesize.m4, m4/pipe2.m4: New files, taken from gnulib.

=== modified file 'configure.ac'
--- configure.ac	2013-07-06 07:04:07 +0000
+++ configure.ac	2013-07-06 21:33:56 +0000
@@ -634,6 +634,19 @@
 # Avoid gnulib's threadlib module, as we do threads our own way.
 AC_DEFUN([gl_THREADLIB])
 
+# On MinGW, Emacs supplies its own substitutes for some missing functions,
+# so hotwire the cache to pretend to Gnulib that the functions work;
+# that way, 'configure' won't arrange to build the Gnulib substitutes.
+if test "$opsys" = mingw32; then
+  # fcntl
+  ac_cv_func_fcntl=emulated # Any single word other than 'no' will do.
+  gl_cv_func_fcntl_f_dupfd_cloexec=yes # Actually 'no', but only 'yes' works.
+  gl_cv_func_fcntl_f_dupfd_works='no, but Emacs emulates yes'
+
+  # pipe2
+  ac_cv_func_pipe2='no, but Emacs emulates yes'
+fi
+
 # Initialize gnulib right after choosing the compiler.
 dnl Amongst other things, this sets AR and ARFLAGS.
 gl_EARLY






Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14803; Package emacs. (Sun, 07 Jul 2013 02:47:02 GMT) Full text and rfc822 format available.

Message #20 received at 14803 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 14803 <at> debbugs.gnu.org
Subject: Re: bug#14803: Setting close-on-exec flag consistently
Date: Sun, 07 Jul 2013 05:46:27 +0300
> Date: Sat, 06 Jul 2013 14:43:26 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: 14803 <at> debbugs.gnu.org
> 
> > I assume that lib/fcntl.c and
> > lib/pipe2.c will not be compiled for w32, due to some configure test?
> 
> Yes, though that needs to be arranged.  The following further
> patch should do it:
> 
> === modified file 'ChangeLog'
> --- ChangeLog	2013-07-06 09:44:23 +0000
> +++ ChangeLog	2013-07-06 21:39:31 +0000
> @@ -1,7 +1,9 @@
>  2013-07-06  Paul Eggert  <eggert <at> cs.ucla.edu>
>  
>  	Make file descriptors close-on-exec when possible (Bug#14803).
> -	* configure.ac (mkostemp): New function to check for.
> +	* configure.ac (ac_cv_func_fcntl, gl_cv_func_fcntl_f_dupfd_cloexec)
> +	(gl_cv_func_fcntl_f_dupfd_works, ac_cv_func_pipe2): Hotwire for MinGW.
> +	(mkostemp): New function to check for.
>  	(PTY_OPEN): Pass O_CLOEXEC to posix_openpt.
>  	* lib/fcntl.c, lib/getdtablesize.c, lib/pipe2.c, m4/fcntl.m4:
>  	* m4/getdtablesize.m4, m4/pipe2.m4: New files, taken from gnulib.
> 
> === modified file 'configure.ac'
> --- configure.ac	2013-07-06 07:04:07 +0000
> +++ configure.ac	2013-07-06 21:33:56 +0000
> @@ -634,6 +634,19 @@
>  # Avoid gnulib's threadlib module, as we do threads our own way.
>  AC_DEFUN([gl_THREADLIB])
>  
> +# On MinGW, Emacs supplies its own substitutes for some missing functions,
> +# so hotwire the cache to pretend to Gnulib that the functions work;
> +# that way, 'configure' won't arrange to build the Gnulib substitutes.
> +if test "$opsys" = mingw32; then
> +  # fcntl
> +  ac_cv_func_fcntl=emulated # Any single word other than 'no' will do.
> +  gl_cv_func_fcntl_f_dupfd_cloexec=yes # Actually 'no', but only 'yes' works.
> +  gl_cv_func_fcntl_f_dupfd_works='no, but Emacs emulates yes'
> +
> +  # pipe2
> +  ac_cv_func_pipe2='no, but Emacs emulates yes'
> +fi
> +

This should probably go into nt/mingw-cfg.site.

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14803; Package emacs. (Sun, 07 Jul 2013 06:35:02 GMT) Full text and rfc822 format available.

Message #23 received at 14803 <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 14803 <at> debbugs.gnu.org
Subject: Re: bug#14803: Setting close-on-exec flag consistently
Date: Sat, 06 Jul 2013 23:34:18 -0700
[Message part 1 (text/plain, inline)]
On 07/06/2013 07:46 PM, Eli Zaretskii wrote:
> This should probably go into nt/mingw-cfg.site.

Thanks, I didn't know about that file.
Also, it strikes me that since MinGW doesn't have pipe2,
there's no need to have "#define pipe2 sys_pipe2".
Revised patch attached.

[cloexec1.diff (text/plain, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#14803; Package emacs. (Sun, 07 Jul 2013 16:47:01 GMT) Full text and rfc822 format available.

Message #26 received at 14803 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Paul Eggert <eggert <at> cs.ucla.edu>
Cc: 14803 <at> debbugs.gnu.org
Subject: Re: bug#14803: Setting close-on-exec flag consistently
Date: Sun, 07 Jul 2013 19:45:32 +0300
> Date: Sat, 06 Jul 2013 23:34:18 -0700
> From: Paul Eggert <eggert <at> cs.ucla.edu>
> CC: 14803 <at> debbugs.gnu.org
> 
> On 07/06/2013 07:46 PM, Eli Zaretskii wrote:
> > This should probably go into nt/mingw-cfg.site.
> 
> Thanks, I didn't know about that file.

Well, it was your idea ;-)

> Also, it strikes me that since MinGW doesn't have pipe2,
> there's no need to have "#define pipe2 sys_pipe2".

Right.

> Revised patch attached.

Thanks, this looks OK to me.




Reply sent to Paul Eggert <eggert <at> cs.ucla.edu>:
You have taken responsibility. (Sun, 07 Jul 2013 18:02:02 GMT) Full text and rfc822 format available.

Notification sent to Paul Eggert <eggert <at> cs.ucla.edu>:
bug acknowledged by developer. (Sun, 07 Jul 2013 18:02:02 GMT) Full text and rfc822 format available.

Message #31 received at 14803-done <at> debbugs.gnu.org (full text, mbox):

From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 14803-done <at> debbugs.gnu.org
Subject: Re: bug#14803: Setting close-on-exec flag consistently
Date: Sun, 07 Jul 2013 11:01:13 -0700
On 07/07/2013 09:45 AM, Eli Zaretskii wrote:

> Thanks, this looks OK to me.

OK, committed as trunk bzr 113315; marking this as done.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Mon, 05 Aug 2013 11:24:03 GMT) Full text and rfc822 format available.

This bug report was last modified 10 years and 273 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.