I’m trying to create a new thread in preexec_fn
and do some fancy stuff, bug only get an unexpected behavior.
I notice these in cpython:
static PyObject *
subprocess_fork_exec(PyObject *module, PyObject *args)
{
.....
/* We need to call gc.disable() when we'll be calling preexec_fn */
if (preexec_fn != Py_None) {
need_to_reenable_gc = PyGC_Disable();
}
......
do_fork_exec(......)
......
}
Py_NO_INLINE static pid_t
do_fork_exec(......)
{
......
if (preexec_fn != Py_None) {
/* We'll be calling back into Python later so we need to do this.
* This call may not be async-signal-safe but neither is calling
* back into Python. The user asked us to use hope as a strategy
* to avoid deadlock... */
PyOS_AfterFork_Child();
}
......
child_exec(.....)
......
}
Py_NO_INLINE static void
child_exec(.....)
{
......
reached_preexec = 1;
if (preexec_fn != Py_None && preexec_fn_args_tuple) {
/* This is where the user has asked us to deadlock their program. */
result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL);
if (result == NULL) {
/* Stringifying the exception or traceback would involve
* memory allocation and thus potential for deadlock.
* We've already faced potential deadlock by calling back
* into Python in the first place, so it probably doesn't
* matter but we avoid it to minimize the possibility. */
err_msg = "Exception occurred in preexec_fn.";
errno = 0; /* We don't want to report an OSError. */
goto error;
}
/* Py_DECREF(result); - We're about to exec so why bother? */
}
......
I’m new to cpython source code, and really don’t know which lock is involved here may lead to deadlock.
BTW, why we need to disable GC before fork?
Appreciated for any information