Skip to content

Commit 8e91c24

Browse files
authored
bpo-36710: Add runtime variable to Py_FinalizeEx() (GH-12937)
* Add a 'runtime' variable to Py_FinalizeEx() rather than working directly on the global variable _PyRuntime * Add a 'runtime' parameter to _PyGC_Fini(), _PyGILState_Fini() and call_ll_exitfuncs()
1 parent 70bf713 commit 8e91c24

File tree

4 files changed

+29
-24
lines changed

4 files changed

+29
-24
lines changed

‎Include/internal/pycore_pylifecycle.h‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11+
#include "pycore_pystate.h" /* _PyRuntimeState */
12+
1113
/* True if the main interpreter thread exited due to an unhandled
1214
* KeyboardInterrupt exception, suggesting the user pressed ^C. */
1315
PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt;
@@ -63,7 +65,7 @@ extern void PyAsyncGen_Fini(void);
6365
extern void _PyExc_Fini(void);
6466
extern void _PyImport_Fini(void);
6567
extern void _PyImport_Fini2(void);
66-
extern void _PyGC_Fini(void);
68+
extern void _PyGC_Fini(_PyRuntimeState *runtime);
6769
extern void _PyType_Fini(void);
6870
extern void _Py_HashRandomization_Fini(void);
6971
extern void _PyUnicode_Fini(void);
@@ -73,7 +75,7 @@ extern void _PyHash_Fini(void);
7375
extern int _PyTraceMalloc_Fini(void);
7476

7577
extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
76-
extern void _PyGILState_Fini(void);
78+
extern void _PyGILState_Fini(_PyRuntimeState *runtime);
7779

7880
PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void);
7981

‎Modules/gcmodule.c‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,9 +1865,10 @@ _PyGC_DumpShutdownStats(void)
18651865
}
18661866

18671867
void
1868-
_PyGC_Fini(void)
1868+
_PyGC_Fini(_PyRuntimeState *runtime)
18691869
{
1870-
Py_CLEAR(_PyRuntime.gc.callbacks);
1870+
struct _gc_runtime_state *gc = &runtime->gc;
1871+
Py_CLEAR(gc->callbacks);
18711872
}
18721873

18731874
/* for debugging */

‎Python/pylifecycle.c‎

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ static _PyInitError init_sys_streams(PyInterpreterState *interp);
6565
static _PyInitError initsigs(void);
6666
static void call_py_exitfuncs(PyInterpreterState *);
6767
static void wait_for_thread_shutdown(void);
68-
static void call_ll_exitfuncs(void);
68+
static void call_ll_exitfuncs(_PyRuntimeState *runtime);
6969

7070
int _Py_UnhandledKeyboardInterrupt = 0;
7171
_PyRuntimeState _PyRuntime = _PyRuntimeState_INIT;
@@ -1131,23 +1131,23 @@ flush_std_files(void)
11311131
int
11321132
Py_FinalizeEx(void)
11331133
{
1134-
PyInterpreterState *interp;
1135-
PyThreadState *tstate;
11361134
int status = 0;
11371135

1138-
if (!_PyRuntime.initialized)
1136+
_PyRuntimeState *runtime = &_PyRuntime;
1137+
if (!runtime->initialized) {
11391138
return status;
1139+
}
11401140

11411141
// Wrap up existing "threading"-module-created, non-daemon threads.
11421142
wait_for_thread_shutdown();
11431143

1144-
/* Get current thread state and interpreter pointer */
1145-
tstate = _PyThreadState_GET();
1146-
interp = tstate->interp;
1147-
11481144
// Make any remaining pending calls.
11491145
_Py_FinishPendingCalls();
11501146

1147+
/* Get current thread state and interpreter pointer */
1148+
PyThreadState *tstate = _PyThreadState_GET();
1149+
PyInterpreterState *interp = tstate->interp;
1150+
11511151
/* The interpreter is still entirely intact at this point, and the
11521152
* exit funcs may be relying on that. In particular, if some thread
11531153
* or exit func is still waiting to do an import, the import machinery
@@ -1174,9 +1174,9 @@ Py_FinalizeEx(void)
11741174

11751175
/* Remaining threads (e.g. daemon threads) will automatically exit
11761176
after taking the GIL (in PyEval_RestoreThread()). */
1177-
_PyRuntime.finalizing = tstate;
1178-
_PyRuntime.initialized = 0;
1179-
_PyRuntime.core_initialized = 0;
1177+
runtime->finalizing = tstate;
1178+
runtime->initialized = 0;
1179+
runtime->core_initialized = 0;
11801180

11811181
/* Flush sys.stdout and sys.stderr */
11821182
if (flush_std_files() < 0) {
@@ -1294,7 +1294,7 @@ Py_FinalizeEx(void)
12941294
PyFloat_Fini();
12951295
PyDict_Fini();
12961296
PySlice_Fini();
1297-
_PyGC_Fini();
1297+
_PyGC_Fini(runtime);
12981298
_Py_HashRandomization_Fini();
12991299
_PyArg_Fini();
13001300
PyAsyncGen_Fini();
@@ -1314,7 +1314,7 @@ Py_FinalizeEx(void)
13141314
PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
13151315

13161316
/* Cleanup auto-thread-state */
1317-
_PyGILState_Fini();
1317+
_PyGILState_Fini(runtime);
13181318

13191319
/* Delete current thread. After this, many C API calls become crashy. */
13201320
PyThreadState_Swap(NULL);
@@ -1336,7 +1336,7 @@ Py_FinalizeEx(void)
13361336
}
13371337
#endif
13381338

1339-
call_ll_exitfuncs();
1339+
call_ll_exitfuncs(runtime);
13401340

13411341
_PyRuntime_Finalize();
13421342
return status;
@@ -2223,10 +2223,11 @@ int Py_AtExit(void (*func)(void))
22232223
}
22242224

22252225
static void
2226-
call_ll_exitfuncs(void)
2226+
call_ll_exitfuncs(_PyRuntimeState *runtime)
22272227
{
2228-
while (_PyRuntime.nexitfuncs > 0)
2229-
(*_PyRuntime.exitfuncs[--_PyRuntime.nexitfuncs])();
2228+
while (runtime->nexitfuncs > 0) {
2229+
(*runtime->exitfuncs[--runtime->nexitfuncs])();
2230+
}
22302231

22312232
fflush(stdout);
22322233
fflush(stderr);

‎Python/pystate.c‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,10 +1078,11 @@ _PyGILState_GetInterpreterStateUnsafe(void)
10781078
}
10791079

10801080
void
1081-
_PyGILState_Fini(void)
1081+
_PyGILState_Fini(_PyRuntimeState *runtime)
10821082
{
1083-
PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey);
1084-
_PyRuntime.gilstate.autoInterpreterState = NULL;
1083+
struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
1084+
PyThread_tss_delete(&gilstate->autoTSSkey);
1085+
gilstate->autoInterpreterState = NULL;
10851086
}
10861087

10871088
/* Reset the TSS key - called by PyOS_AfterFork_Child().

0 commit comments

Comments
 (0)