Skip to content

Commit d3b4e06

Browse files
Alexey Izbyshevgpshead
andauthored
bpo-42146: Unify cleanup in subprocess_fork_exec() (GH-22970)
* bpo-42146: Unify cleanup in subprocess_fork_exec() Also ignore errors from _enable_gc(): * They are always suppressed by the current code due to a bug. * _enable_gc() is only used if `preexec_fn != None`, which is unsafe. * We don't have a good way to handle errors in case we successfully created a child process. Co-authored-by: Gregory P. Smith <[email protected]>
1 parent 3bf0d02 commit d3b4e06

File tree

1 file changed

+18
-35
lines changed

1 file changed

+18
-35
lines changed

Modules/_posixsubprocess.c

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ get_posixsubprocess_state(PyObject *module)
8787

8888
#define _posixsubprocessstate_global get_posixsubprocess_state(PyState_FindModule(&_posixsubprocessmodule))
8989

90-
/* If gc was disabled, call gc.enable(). Return 0 on success. */
91-
static int
90+
/* If gc was disabled, call gc.enable(). Ignore errors. */
91+
static void
9292
_enable_gc(int need_to_reenable_gc, PyObject *gc_module)
9393
{
9494
PyObject *result;
@@ -98,15 +98,17 @@ _enable_gc(int need_to_reenable_gc, PyObject *gc_module)
9898
PyErr_Fetch(&exctype, &val, &tb);
9999
result = PyObject_CallMethodNoArgs(
100100
gc_module, _posixsubprocessstate_global->enable);
101+
if (result == NULL) {
102+
/* We might have created a child process at this point, we
103+
* we have no good way to handle a failure to reenable GC
104+
* and return information about the child process. */
105+
PyErr_Print();
106+
}
107+
Py_XDECREF(result);
101108
if (exctype != NULL) {
102109
PyErr_Restore(exctype, val, tb);
103110
}
104-
if (result == NULL) {
105-
return 1;
106-
}
107-
Py_DECREF(result);
108111
}
109-
return 0;
110112
}
111113

112114

@@ -774,7 +776,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
774776
int child_umask;
775777
PyObject *cwd_obj, *cwd_obj2 = NULL;
776778
const char *cwd;
777-
pid_t pid;
779+
pid_t pid = -1;
778780
int need_to_reenable_gc = 0;
779781
char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
780782
Py_ssize_t arg_num, num_groups = 0;
@@ -1010,8 +1012,6 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
10101012
sigset_t all_sigs;
10111013
sigfillset(&all_sigs);
10121014
if ((saved_errno = pthread_sigmask(SIG_BLOCK, &all_sigs, &old_sigs))) {
1013-
errno = saved_errno;
1014-
PyErr_SetFromErrno(PyExc_OSError);
10151015
goto cleanup;
10161016
}
10171017
old_sigmask = &old_sigs;
@@ -1050,50 +1050,33 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
10501050
}
10511051
#endif
10521052

1053-
Py_XDECREF(cwd_obj2);
1054-
10551053
if (need_after_fork)
10561054
PyOS_AfterFork_Parent();
1057-
if (envp)
1058-
_Py_FreeCharPArray(envp);
1059-
if (argv)
1060-
_Py_FreeCharPArray(argv);
1061-
_Py_FreeCharPArray(exec_array);
1062-
1063-
/* Reenable gc in the parent process (or if fork failed). */
1064-
if (_enable_gc(need_to_reenable_gc, gc_module)) {
1065-
pid = -1;
1066-
}
1067-
PyMem_RawFree(groups);
1068-
Py_XDECREF(preexec_fn_args_tuple);
1069-
Py_XDECREF(gc_module);
10701055

1071-
if (pid == -1) {
1056+
cleanup:
1057+
if (saved_errno != 0) {
10721058
errno = saved_errno;
10731059
/* We can't call this above as PyOS_AfterFork_Parent() calls back
10741060
* into Python code which would see the unreturned error. */
10751061
PyErr_SetFromErrno(PyExc_OSError);
1076-
return NULL; /* fork() failed. */
10771062
}
10781063

1079-
return PyLong_FromPid(pid);
1080-
1081-
cleanup:
1064+
Py_XDECREF(preexec_fn_args_tuple);
1065+
PyMem_RawFree(groups);
10821066
Py_XDECREF(cwd_obj2);
10831067
if (envp)
10841068
_Py_FreeCharPArray(envp);
1069+
Py_XDECREF(converted_args);
1070+
Py_XDECREF(fast_args);
10851071
if (argv)
10861072
_Py_FreeCharPArray(argv);
10871073
if (exec_array)
10881074
_Py_FreeCharPArray(exec_array);
10891075

1090-
PyMem_RawFree(groups);
1091-
Py_XDECREF(converted_args);
1092-
Py_XDECREF(fast_args);
1093-
Py_XDECREF(preexec_fn_args_tuple);
10941076
_enable_gc(need_to_reenable_gc, gc_module);
10951077
Py_XDECREF(gc_module);
1096-
return NULL;
1078+
1079+
return pid == -1 ? NULL : PyLong_FromPid(pid);
10971080
}
10981081

10991082

0 commit comments

Comments
 (0)