bpo-39877: _PyRuntimeState.finalizing becomes atomic (GH-18816)

Convert _PyRuntimeState.finalizing field to an atomic variable:

* Rename it to _finalizing
* Change its type to _Py_atomic_address
* Add _PyRuntimeState_GetFinalizing() and _PyRuntimeState_SetFinalizing()
  functions
* Remove _Py_CURRENTLY_FINALIZING() function: replace it with testing
  directly _PyRuntimeState_GetFinalizing() value

Convert _PyRuntimeState_GetThreadState() to static inline function.
This commit is contained in:
Victor Stinner 2020-03-07 00:24:23 +01:00 committed by GitHub
parent 557287075c
commit 7b3c252dc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 15 deletions

View file

@ -240,7 +240,8 @@ exit_thread_if_finalizing(PyThreadState *tstate)
{
_PyRuntimeState *runtime = tstate->interp->runtime;
/* _Py_Finalizing is protected by the GIL */
if (runtime->finalizing != NULL && !_Py_CURRENTLY_FINALIZING(runtime, tstate)) {
PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime);
if (finalizing != NULL && finalizing != tstate) {
drop_gil(&runtime->ceval, tstate);
PyThread_exit_thread();
}

View file

@ -103,7 +103,7 @@ _PyRuntime_Finalize(void)
int
_Py_IsFinalizing(void)
{
return _PyRuntime.finalizing != NULL;
return _PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL;
}
/* Hack to force loading of object files */
@ -507,7 +507,7 @@ pycore_init_runtime(_PyRuntimeState *runtime,
* threads still hanging around from a previous Py_Initialize/Finalize
* pair :(
*/
runtime->finalizing = NULL;
_PyRuntimeState_SetFinalizing(runtime, NULL);
PyStatus status = _Py_HashRandomization_Init(config);
if (_PyStatus_EXCEPTION(status)) {
@ -1366,7 +1366,7 @@ Py_FinalizeEx(void)
/* Remaining threads (e.g. daemon threads) will automatically exit
after taking the GIL (in PyEval_RestoreThread()). */
runtime->finalizing = tstate;
_PyRuntimeState_SetFinalizing(runtime, tstate);
runtime->initialized = 0;
runtime->core_initialized = 0;
@ -2131,8 +2131,9 @@ static void
fatal_error_dump_runtime(FILE *stream, _PyRuntimeState *runtime)
{
fprintf(stream, "Python runtime state: ");
if (runtime->finalizing) {
fprintf(stream, "finalizing (tstate=%p)", runtime->finalizing);
PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime);
if (finalizing) {
fprintf(stream, "finalizing (tstate=%p)", finalizing);
}
else if (runtime->initialized) {
fprintf(stream, "initialized");

View file

@ -292,7 +292,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
Py_CLEAR(interp->after_forkers_parent);
Py_CLEAR(interp->after_forkers_child);
#endif
if (runtime->finalizing == NULL) {
if (_PyRuntimeState_GetFinalizing(runtime) == NULL) {
_PyWarnings_Fini(interp);
}
// XXX Once we have one allocator per interpreter (i.e.

View file

@ -289,8 +289,9 @@ _PySys_ClearAuditHooks(void)
/* Must be finalizing to clear hooks */
_PyRuntimeState *runtime = &_PyRuntime;
PyThreadState *ts = _PyRuntimeState_GetThreadState(runtime);
assert(!ts || _Py_CURRENTLY_FINALIZING(runtime, ts));
if (!ts || !_Py_CURRENTLY_FINALIZING(runtime, ts)) {
PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime);
assert(!ts || finalizing == ts);
if (!ts || finalizing != ts) {
return;
}