[Python-checkins] cpython (merge 3.4 -> default): (Merge 3.4) Closes #22258: Fix the the internal function set_inheritable() on

victor.stinner python-checkins at python.org
Tue Sep 2 11:50:10 CEST 2014


http://hg.python.org/cpython/rev/4a51c45f405b
changeset:   92302:4a51c45f405b
parent:      92300:3dafa5f1dc04
parent:      92301:27cef7476f2b
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Tue Sep 02 11:49:48 2014 +0200
summary:
  (Merge 3.4) Closes #22258: Fix the the internal function set_inheritable() on
Illumos.  This platform exposes the function ioctl(FIOCLEX), but calling it
fails with errno is ENOTTY: "Inappropriate ioctl for device". set_inheritable()
now falls back to the slower fcntl() (F_GETFD and then F_SETFD).

files:
  Misc/NEWS          |   5 +++
  Python/fileutils.c |  48 ++++++++++++++++++++++++---------
  2 files changed, 39 insertions(+), 14 deletions(-)


diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,11 @@
 Core and Builtins
 -----------------
 
+- Issue #22258: Fix the the internal function set_inheritable() on Illumos.
+  This platform exposes the function ``ioctl(FIOCLEX)``, but calling it fails
+  with errno is ENOTTY: "Inappropriate ioctl for device". set_inheritable()
+  now falls back to the slower ``fcntl()`` (``F_GETFD`` and then ``F_SETFD``).
+
 - Issue #21389: Displaying the __qualname__ of the underlying function in the
   repr of a bound method.
 
diff --git a/Python/fileutils.c b/Python/fileutils.c
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -625,10 +625,12 @@
 #ifdef MS_WINDOWS
     HANDLE handle;
     DWORD flags;
-#elif defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
+#else
+#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
+    static int ioctl_works = -1;
     int request;
     int err;
-#elif defined(HAVE_FCNTL_H)
+#endif
     int flags;
     int res;
 #endif
@@ -674,20 +676,38 @@
     }
     return 0;
 
-#elif defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
-    if (inheritable)
-        request = FIONCLEX;
-    else
-        request = FIOCLEX;
-    err = ioctl(fd, request, NULL);
-    if (err) {
-        if (raise)
-            PyErr_SetFromErrno(PyExc_OSError);
-        return -1;
+#else
+
+#if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
+    if (ioctl_works != 0) {
+        /* fast-path: ioctl() only requires one syscall */
+        if (inheritable)
+            request = FIONCLEX;
+        else
+            request = FIOCLEX;
+        err = ioctl(fd, request, NULL);
+        if (!err) {
+            ioctl_works = 1;
+            return 0;
+        }
+
+        if (errno != ENOTTY) {
+            if (raise)
+                PyErr_SetFromErrno(PyExc_OSError);
+            return -1;
+        }
+        else {
+            /* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for
+               device". The ioctl is declared but not supported by the kernel.
+               Remember that ioctl() doesn't work. It is the case on
+               Illumos-based OS for example. */
+            ioctl_works = 0;
+        }
+        /* fallback to fcntl() if ioctl() does not work */
     }
-    return 0;
+#endif
 
-#else
+    /* slow-path: fcntl() requires two syscalls */
     flags = fcntl(fd, F_GETFD);
     if (flags < 0) {
         if (raise)

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list