void *arg);
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate);
#ifdef HAVE_FORK
-extern void _PyEval_ReInitThreads(struct pyruntimestate *runtime);
+extern PyStatus _PyEval_ReInitThreads(struct pyruntimestate *runtime);
#endif
PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth(
PyThreadState *tstate,
);
#ifdef HAVE_FORK
-extern void _PyImport_ReInitLock(void);
+extern PyStatus _PyImport_ReInitLock(void);
#endif
extern void _PyImport_Cleanup(PyThreadState *tstate);
PyThreadState *newts);
PyAPI_FUNC(PyStatus) _PyInterpreterState_Enable(_PyRuntimeState *runtime);
-PyAPI_FUNC(void) _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);
-PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
+#ifdef HAVE_FORK
+extern PyStatus _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);
+extern PyStatus _PyGILState_Reinit(_PyRuntimeState *runtime);
+extern void _PySignal_AfterFork(void);
+#endif
PyAPI_FUNC(int) _PyState_AddModule(
PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime);
#ifdef HAVE_FORK
-PyAPI_FUNC(void) _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime);
+extern PyStatus _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime);
#endif
/* Initialize _PyRuntimeState.
-
#ifndef Py_INTRCHECK_H
#define Py_INTRCHECK_H
#ifdef __cplusplus
#ifndef Py_LIMITED_API
PyAPI_FUNC(int) _PyOS_IsMainThread(void);
-PyAPI_FUNC(void) _PySignal_AfterFork(void);
#ifdef MS_WINDOWS
/* windows.h is not included by Python.h so use void* instead of HANDLE */
#include "pycore_ceval.h" // _PyEval_ReInitThreads()
#include "pycore_import.h" // _PyImport_ReInitLock()
+#include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "structmember.h" // PyMemberDef
#ifndef MS_WINDOWS
void
PyOS_AfterFork_Child(void)
{
+ PyStatus status;
_PyRuntimeState *runtime = &_PyRuntime;
- _PyGILState_Reinit(runtime);
- _PyEval_ReInitThreads(runtime);
- _PyImport_ReInitLock();
+
+ status = _PyGILState_Reinit(runtime);
+ if (_PyStatus_EXCEPTION(status)) {
+ goto fatal_error;
+ }
+
+ status = _PyEval_ReInitThreads(runtime);
+ if (_PyStatus_EXCEPTION(status)) {
+ goto fatal_error;
+ }
+
+ status = _PyImport_ReInitLock();
+ if (_PyStatus_EXCEPTION(status)) {
+ goto fatal_error;
+ }
+
_PySignal_AfterFork();
- _PyRuntimeState_ReInitThreads(runtime);
- _PyInterpreterState_DeleteExceptMain(runtime);
+
+ status = _PyRuntimeState_ReInitThreads(runtime);
+ if (_PyStatus_EXCEPTION(status)) {
+ goto fatal_error;
+ }
+
+ status = _PyInterpreterState_DeleteExceptMain(runtime);
+ if (_PyStatus_EXCEPTION(status)) {
+ goto fatal_error;
+ }
run_at_forkers(_PyInterpreterState_GET()->after_forkers_child, 0);
+ return;
+
+fatal_error:
+ Py_ExitStatusException(status);
}
static int
return 1;
}
+
+#ifdef HAVE_FORK
static void
_clear_pending_signals(void)
{
- int i;
- if (!_Py_atomic_load(&is_tripped))
+ if (!_Py_atomic_load(&is_tripped)) {
return;
+ }
+
_Py_atomic_store(&is_tripped, 0);
- for (i = 1; i < NSIG; ++i) {
+ for (int i = 1; i < NSIG; ++i) {
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
}
}
* the interpreter had an opportunity to call the handlers. issue9535. */
_clear_pending_signals();
}
+#endif /* HAVE_FORK */
+
int
_PyOS_IsMainThread(void)
#ifdef HAVE_FORK
/* This function is called from PyOS_AfterFork_Child to destroy all threads
- * which are not running in the child process, and clear internal locks
- * which might be held by those threads.
- */
-
-void
+ which are not running in the child process, and clear internal locks
+ which might be held by those threads. */
+PyStatus
_PyEval_ReInitThreads(_PyRuntimeState *runtime)
{
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
struct _gil_runtime_state *gil = &runtime->ceval.gil;
#endif
if (!gil_created(gil)) {
- return;
+ return _PyStatus_OK();
}
recreate_gil(gil);
struct _pending_calls *pending = &tstate->interp->ceval.pending;
if (_PyThread_at_fork_reinit(&pending->lock) < 0) {
- Py_FatalError("Can't initialize threads for pending calls");
+ return _PyStatus_ERR("Can't reinitialize pending calls lock");
}
/* Destroy all threads except the current one */
_PyThreadState_DeleteExcept(runtime, tstate);
+ return _PyStatus_OK();
}
#endif
in different threads to return with a partially loaded module.
These calls are serialized by the global interpreter lock. */
-static PyThread_type_lock import_lock = 0;
+static PyThread_type_lock import_lock = NULL;
static unsigned long import_lock_thread = PYTHREAD_INVALID_THREAD_ID;
static int import_lock_level = 0;
!PyThread_acquire_lock(import_lock, 0))
{
PyThreadState *tstate = PyEval_SaveThread();
- PyThread_acquire_lock(import_lock, 1);
+ PyThread_acquire_lock(import_lock, WAIT_LOCK);
PyEval_RestoreThread(tstate);
}
assert(import_lock_level == 0);
}
#ifdef HAVE_FORK
-/* This function is called from PyOS_AfterFork_Child to ensure that newly
+/* This function is called from PyOS_AfterFork_Child() to ensure that newly
created child processes do not share locks with the parent.
We now acquire the import lock around fork() calls but on some platforms
(Solaris 9 and earlier? see isue7242) that still left us with problems. */
-
-void
+PyStatus
_PyImport_ReInitLock(void)
{
if (import_lock != NULL) {
if (_PyThread_at_fork_reinit(&import_lock) < 0) {
- _Py_FatalErrorFunc(__func__, "failed to create a new lock");
+ return _PyStatus_ERR("failed to create a new lock");
}
}
+
if (import_lock_level > 1) {
/* Forked as a side effect of import */
unsigned long me = PyThread_get_thread_ident();
import_lock_thread = PYTHREAD_INVALID_THREAD_ID;
import_lock_level = 0;
}
+ return _PyStatus_OK();
}
#endif
#ifdef HAVE_FORK
/* This function is called from PyOS_AfterFork_Child to ensure that
- * newly created child processes do not share locks with the parent.
- */
-
-void
+ newly created child processes do not share locks with the parent. */
+PyStatus
_PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
{
// This was initially set in _PyRuntimeState_Init().
PyMemAllocatorEx old_alloc;
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
- int interp_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.mutex);
- int main_interp_id_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex);
- int xidregistry_mutex = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex);
+ int reinit_interp = _PyThread_at_fork_reinit(&runtime->interpreters.mutex);
+ int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex);
+ int reinit_xidregistry = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex);
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
- if (interp_mutex < 0) {
- Py_FatalError("Can't initialize lock for runtime interpreters");
- }
-
- if (main_interp_id_mutex < 0) {
- Py_FatalError("Can't initialize ID lock for main interpreter");
- }
+ if (reinit_interp < 0
+ || reinit_main_id < 0
+ || reinit_xidregistry < 0)
+ {
+ return _PyStatus_ERR("Failed to reinitialize runtime locks");
- if (xidregistry_mutex < 0) {
- Py_FatalError("Can't initialize lock for cross-interpreter data registry");
}
+ return _PyStatus_OK();
}
#endif
}
+#ifdef HAVE_FORK
/*
* Delete all interpreter states except the main interpreter. If there
* is a current interpreter state, it *must* be the main interpreter.
*/
-void
+PyStatus
_PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
{
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL);
if (tstate != NULL && tstate->interp != interpreters->main) {
- Py_FatalError("not main interpreter");
+ return _PyStatus_ERR("not main interpreter");
}
HEAD_LOCK(runtime);
HEAD_UNLOCK(runtime);
if (interpreters->head == NULL) {
- Py_FatalError("missing main interpreter");
+ return _PyStatus_ERR("missing main interpreter");
}
_PyThreadState_Swap(gilstate, tstate);
+ return _PyStatus_OK();
}
+#endif
PyInterpreterState *
gilstate->autoInterpreterState = NULL;
}
+#ifdef HAVE_FORK
/* Reset the TSS key - called by PyOS_AfterFork_Child().
* This should not be necessary, but some - buggy - pthread implementations
* don't reset TSS upon fork(), see issue #10517.
*/
-void
+PyStatus
_PyGILState_Reinit(_PyRuntimeState *runtime)
{
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
PyThread_tss_delete(&gilstate->autoTSSkey);
if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) {
- Py_FatalError("Could not allocate TSS entry");
+ return _PyStatus_NO_MEMORY();
}
/* If the thread had an associated auto thread state, reassociate it with
if (tstate &&
PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate) != 0)
{
- Py_FatalError("Couldn't create autoTSSkey mapping");
+ return _PyStatus_ERR("failed to set autoTSSkey");
}
+ return _PyStatus_OK();
}
+#endif
/* When a thread state is created for a thread by some mechanism other than
PyGILState_Ensure, it's important that the GILState machinery knows about