Commit 8257b628 authored by Victor Stinner's avatar Victor Stinner

(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).
parents 7809569a 282124b8
...@@ -10,6 +10,11 @@ Release date: TBA ...@@ -10,6 +10,11 @@ Release date: TBA
Core and Builtins 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 - Issue #21389: Displaying the __qualname__ of the underlying function in the
repr of a bound method. repr of a bound method.
......
...@@ -625,10 +625,12 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) ...@@ -625,10 +625,12 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
HANDLE handle; HANDLE handle;
DWORD flags; 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 request;
int err; int err;
#elif defined(HAVE_FCNTL_H) #endif
int flags; int flags;
int res; int res;
#endif #endif
...@@ -674,20 +676,38 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) ...@@ -674,20 +676,38 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
} }
return 0; return 0;
#elif defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) #else
if (inheritable)
request = FIONCLEX; #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX)
else if (ioctl_works != 0) {
request = FIOCLEX; /* fast-path: ioctl() only requires one syscall */
err = ioctl(fd, request, NULL); if (inheritable)
if (err) { request = FIONCLEX;
if (raise) else
PyErr_SetFromErrno(PyExc_OSError); request = FIOCLEX;
return -1; 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); flags = fcntl(fd, F_GETFD);
if (flags < 0) { if (flags < 0) {
if (raise) if (raise)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment