Skip to content

Commit b2ff9a9

Browse files
bpo-34658: Fix rare subprocess prexec_fn fork error. (GH-9255)
[bpo-34658](https://www.bugs.python.org/issue34658): Fix a rare interpreter unhandled exception state SystemError only seen when using subprocess with a preexec_fn while an after_parent handler has been registered with os.register_at_fork and the fork system call fails. https://bugs.python.org/issue34658 (cherry picked from commit a20b6ad) Co-authored-by: Gregory P. Smith <greg@krypto.org>
1 parent 35c94c7 commit b2ff9a9

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a rare interpreter unhandled exception state SystemError only seen when
2+
using subprocess with a preexec_fn while an after_parent handler has been
3+
registered with os.register_at_fork and the fork system call fails.

Modules/_posixsubprocess.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
564564
char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
565565
Py_ssize_t arg_num;
566566
int need_after_fork = 0;
567+
int saved_errno = 0;
567568

568569
if (!PyArg_ParseTuple(
569570
args, "OOpO!OOiiiiiiiiiiO:fork_exec",
@@ -700,14 +701,14 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
700701
_exit(255);
701702
return NULL; /* Dead code to avoid a potential compiler warning. */
702703
}
703-
Py_XDECREF(cwd_obj2);
704-
704+
/* Parent (original) process */
705705
if (pid == -1) {
706-
/* Capture the errno exception before errno can be clobbered. */
707-
PyErr_SetFromErrno(PyExc_OSError);
706+
/* Capture errno for the exception. */
707+
saved_errno = errno;
708708
}
709709

710-
/* Parent process */
710+
Py_XDECREF(cwd_obj2);
711+
711712
if (need_after_fork)
712713
PyOS_AfterFork_Parent();
713714
if (envp)
@@ -723,8 +724,13 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
723724
Py_XDECREF(preexec_fn_args_tuple);
724725
Py_XDECREF(gc_module);
725726

726-
if (pid == -1)
727-
return NULL; /* fork() failed. Exception set earlier. */
727+
if (pid == -1) {
728+
errno = saved_errno;
729+
/* We can't call this above as PyOS_AfterFork_Parent() calls back
730+
* into Python code which would see the unreturned error. */
731+
PyErr_SetFromErrno(PyExc_OSError);
732+
return NULL; /* fork() failed. */
733+
}
728734

729735
return PyLong_FromPid(pid);
730736

0 commit comments

Comments
 (0)