[pypy-commit] pypy py3.5-noninherit: copy the logic from 3.5 to inherit some file descriptors

arigo pypy.commits at gmail.com
Fri Aug 26 14:03:39 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5-noninherit
Changeset: r86583:f00bf6596800
Date: 2016-08-26 20:03 +0200
http://bitbucket.org/pypy/pypy/changeset/f00bf6596800/

Log:	copy the logic from 3.5 to inherit some file descriptors

diff --git a/pypy/module/_posixsubprocess/_posixsubprocess.c b/pypy/module/_posixsubprocess/_posixsubprocess.c
--- a/pypy/module/_posixsubprocess/_posixsubprocess.c
+++ b/pypy/module/_posixsubprocess/_posixsubprocess.c
@@ -106,6 +106,30 @@
 }
 
 
+RPY_EXTERN
+int rpy_set_inheritable(int fd, int inheritable);   /* rposix.py */
+
+static int
+make_inheritable(long *py_fds_to_keep, ssize_t num_fds_to_keep,
+                 int errpipe_write)
+{
+    long i;
+
+    for (i = 0; i < num_fds_to_keep; ++i) {
+        long fd = py_fds_to_keep[i];
+        if (fd == errpipe_write) {
+            /* errpipe_write is part of py_fds_to_keep. It must be closed at
+               exec(), but kept open in the child process until exec() is
+               called. */
+            continue;
+        }
+        if (rpy_set_inheritable((int)fd, 1) < 0)
+            return -1;
+    }
+    return 0;
+}
+
+
 /* Close all file descriptors in the range start_fd inclusive to
  * end_fd exclusive except for those in py_fds_to_keep.  If the
  * range defined by [start_fd, end_fd) is large this will take a
@@ -329,6 +353,9 @@
     /* Buffer large enough to hold a hex integer.  We can't malloc. */
     char hex_errno[sizeof(saved_errno)*2+1];
 
+    if (make_inheritable(py_fds_to_keep, num_fds_to_keep, errpipe_write) < 0)
+        goto error;
+
     /* Close parent's pipe ends. */
     if (p2cwrite != -1) {
         POSIX_CALL(close(p2cwrite));
@@ -352,26 +379,25 @@
        dup2() removes the CLOEXEC flag but we must do it ourselves if dup2()
        would be a no-op (issue #10806). */
     if (p2cread == 0) {
-        int old = fcntl(p2cread, F_GETFD);
-        if (old != -1)
-            fcntl(p2cread, F_SETFD, old & ~FD_CLOEXEC);
-    } else if (p2cread != -1) {
+        if (rpy_set_inheritable(p2cread, 1) < 0)
+            goto error;
+    }
+    else if (p2cread != -1)
         POSIX_CALL(dup2(p2cread, 0));  /* stdin */
+
+    if (c2pwrite == 1) {
+        if (rpy_set_inheritable(c2pwrite, 1) < 0)
+            goto error;
     }
-    if (c2pwrite == 1) {
-        int old = fcntl(c2pwrite, F_GETFD);
-        if (old != -1)
-            fcntl(c2pwrite, F_SETFD, old & ~FD_CLOEXEC);
-    } else if (c2pwrite != -1) {
+    else if (c2pwrite != -1)
         POSIX_CALL(dup2(c2pwrite, 1));  /* stdout */
+
+    if (errwrite == 2) {
+        if (rpy_set_inheritable(errwrite, 1) < 0)
+            goto error;
     }
-    if (errwrite == 2) {
-        int old = fcntl(errwrite, F_GETFD);
-        if (old != -1)
-            fcntl(errwrite, F_SETFD, old & ~FD_CLOEXEC);
-    } else if (errwrite != -1) {
+    else if (errwrite != -1)
         POSIX_CALL(dup2(errwrite, 2));  /* stderr */
-    }
 
     /* Close pipe fds.  Make sure we don't close the same fd more than */
     /* once, or standard fds. */
diff --git a/pypy/module/_posixsubprocess/_posixsubprocess.h b/pypy/module/_posixsubprocess/_posixsubprocess.h
--- a/pypy/module/_posixsubprocess/_posixsubprocess.h
+++ b/pypy/module/_posixsubprocess/_posixsubprocess.h
@@ -1,3 +1,4 @@
+#include <unistd.h>    /* for ssize_t */
 #include "src/precommondefs.h"
 
 RPY_EXTERN void
diff --git a/pypy/module/_posixsubprocess/interp_subprocess.py b/pypy/module/_posixsubprocess/interp_subprocess.py
--- a/pypy/module/_posixsubprocess/interp_subprocess.py
+++ b/pypy/module/_posixsubprocess/interp_subprocess.py
@@ -5,6 +5,7 @@
 from rpython.rtyper.tool import rffi_platform as platform
 from rpython.translator import cdir
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rlib import rposix
 
 from pypy.interpreter.error import (
     OperationError, exception_from_saved_errno, oefmt, wrap_oserror)
@@ -36,6 +37,7 @@
     compile_extra.append("-DHAVE_SETSID")
 
 eci = eci.merge(
+    rposix.eci_inheritable,
     ExternalCompilationInfo(
         compile_extra=compile_extra))
 
diff --git a/pypy/module/_posixsubprocess/test/test_subprocess.py b/pypy/module/_posixsubprocess/test/test_subprocess.py
--- a/pypy/module/_posixsubprocess/test/test_subprocess.py
+++ b/pypy/module/_posixsubprocess/test/test_subprocess.py
@@ -75,3 +75,18 @@
         n = 1
         raises(OverflowError, _posixsubprocess.fork_exec,
                1,Z(),3,[1, 2],5,6,7,8,9,10,11,12,13,14,15,16,17)
+
+    def test_pass_fds_make_inheritable(self):
+        import subprocess, posix
+
+        fd1, fd2 = posix.pipe()
+        assert posix.get_inheritable(fd1) is False
+        assert posix.get_inheritable(fd2) is False
+
+        subprocess.check_call(['/usr/bin/env', 'python', '-c',
+                               'import os;os.write(%d,b"K")' % fd2],
+                              close_fds=True, pass_fds=[fd2])
+        res = posix.read(fd1, 1)
+        assert res == b"K"
+        posix.close(fd1)
+        posix.close(fd2)


More information about the pypy-commit mailing list