bpo-32777: Fix _Py_set_inheritable async-safety in subprocess (GH-5560) · pythoncapi/cpython@c1e46e9 · GitHub
Skip to content

Commit c1e46e9

Browse files
izbyshevgpshead
authored andcommitted
bpo-32777: Fix _Py_set_inheritable async-safety in subprocess (pythonGH-5560)
Fix a rare but potential pre-exec child process deadlock in subprocess on POSIX systems when marking file descriptors inheritable on exec in the child process. This bug appears to have been introduced in 3.4 with the inheritable file descriptors support. This also changes Python/fileutils.c `set_inheritable` to use the "slow" two `fcntl` syscall path instead of the "fast" single `ioctl` syscall path when asked to be async signal safe (by way of being asked not to raise exceptions). `ioctl` is not a POSIX async-signal-safe approved function. ref: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
1 parent 22864bc commit c1e46e9

4 files changed

Lines changed: 26 additions & 7 deletions

File tree

Include/fileutils.h

Lines changed: 3 additions & 0 deletions
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a rare but potential pre-exec child process deadlock in subprocess on
2+
POSIX systems when marking file descriptors inheritable on exec in the child
3+
process. This bug appears to have been introduced in 3.4.

Modules/_posixsubprocess.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ make_inheritable(PyObject *py_fds_to_keep, int errpipe_write)
169169
called. */
170170
continue;
171171
}
172-
if (_Py_set_inheritable((int)fd, 1, NULL) < 0)
172+
if (_Py_set_inheritable_async_safe((int)fd, 1, NULL) < 0)
173173
return -1;
174174
}
175175
return 0;
@@ -431,21 +431,21 @@ child_exec(char *const exec_array[],
431431
dup2() removes the CLOEXEC flag but we must do it ourselves if dup2()
432432
would be a no-op (issue #10806). */
433433
if (p2cread == 0) {
434-
if (_Py_set_inheritable(p2cread, 1, NULL) < 0)
434+
if (_Py_set_inheritable_async_safe(p2cread, 1, NULL) < 0)
435435
goto error;
436436
}
437437
else if (p2cread != -1)
438438
POSIX_CALL(dup2(p2cread, 0)); /* stdin */
439439

440440
if (c2pwrite == 1) {
441-
if (_Py_set_inheritable(c2pwrite, 1, NULL) < 0)
441+
if (_Py_set_inheritable_async_safe(c2pwrite, 1, NULL) < 0)
442442
goto error;
443443
}
444444
else if (c2pwrite != -1)
445445
POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */
446446

447447
if (errwrite == 2) {
448-
if (_Py_set_inheritable(errwrite, 1, NULL) < 0)
448+
if (_Py_set_inheritable_async_safe(errwrite, 1, NULL) < 0)
449449
goto error;
450450
}
451451
else if (errwrite != -1)

Python/fileutils.c

Lines changed: 16 additions & 3 deletions

0 commit comments

Comments
 (0)