diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 86dada5061e7b5..29bf1377327125 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -43,6 +43,10 @@ struct _Py_long_state { int max_str_digits; }; +struct _getargs_runtime_state { + struct _PyArg_Parser *static_parsers; +}; + // Support for stop-the-world events. This exists in both the PyRuntime struct // for global pauses and in each PyInterpreterState for per-interpreter pauses. struct _stoptheworld_state { @@ -211,6 +215,7 @@ struct _is { PyObject *after_forkers_child; #endif + struct _getargs_runtime_state getargs; struct _warnings_runtime_state warnings; struct atexit_state atexit; struct _stoptheworld_state stoptheworld; diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index f426ae0e103b9c..113f417c67b6fe 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -57,7 +57,8 @@ extern void _PyWarnings_Fini(PyInterpreterState *interp); extern void _PyAST_Fini(PyInterpreterState *interp); extern void _PyAtExit_Fini(PyInterpreterState *interp); extern void _PyThread_FiniType(PyInterpreterState *interp); -extern void _PyArg_Fini(void); +extern void _PyArg_InitState(PyInterpreterState *interp); +extern void _PyArg_Fini(PyInterpreterState *interp); extern void _Py_FinalizeAllocatedBlocks(_PyRuntimeState *); extern PyStatus _PyGILState_Init(PyInterpreterState *interp); diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h index f58eccf729cb2a..582695a6d35df7 100644 --- a/Include/internal/pycore_runtime.h +++ b/Include/internal/pycore_runtime.h @@ -25,10 +25,6 @@ extern "C" { #include "pycore_typeobject.h" // struct _types_runtime_state #include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_state -struct _getargs_runtime_state { - struct _PyArg_Parser *static_parsers; -}; - /* GIL state */ struct _gilstate_runtime_state { @@ -238,7 +234,6 @@ typedef struct pyruntimestate { struct _import_runtime_state imports; struct _ceval_runtime_state ceval; struct _gilstate_runtime_state gilstate; - struct _getargs_runtime_state getargs; struct _fileutils_state fileutils; struct _faulthandler_runtime_state faulthandler; struct _tracemalloc_runtime_state tracemalloc; diff --git a/Python/getargs.c b/Python/getargs.c index 539925e471f54c..389fbb4c1ac544 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -9,6 +9,7 @@ #include "pycore_pylifecycle.h" // _PyArg_Fini #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_pyerrors.h" // _Py_CalculateSuggestions() +#include "pycore_interp.h" // _getargs_runtime_state /* Export Stable ABIs (abi only) */ PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...); @@ -1966,10 +1967,11 @@ _parser_init(void *arg) parser->is_kwtuple_owned = owned; assert(parser->next == NULL); - parser->next = _Py_atomic_load_ptr(&_PyRuntime.getargs.static_parsers); + PyInterpreterState *interp = PyInterpreterState_Get(); + parser->next = _Py_atomic_load_ptr(&interp->getargs.static_parsers); do { // compare-exchange updates parser->next on failure - } while (_Py_atomic_compare_exchange_ptr(&_PyRuntime.getargs.static_parsers, + } while (_Py_atomic_compare_exchange_ptr(&interp->getargs.static_parsers, &parser->next, parser)); return 0; } @@ -2878,14 +2880,20 @@ _PyArg_NoKwnames(const char *funcname, PyObject *kwnames) } void -_PyArg_Fini(void) +_PyArg_InitState(PyInterpreterState *interp) { - struct _PyArg_Parser *tmp, *s = _PyRuntime.getargs.static_parsers; + interp->getargs.static_parsers = NULL; +} + +void +_PyArg_Fini(PyInterpreterState *interp) +{ + struct _PyArg_Parser *tmp, *s = interp->getargs.static_parsers; while (s) { tmp = s->next; s->next = NULL; parser_clear(s); s = tmp; } - _PyRuntime.getargs.static_parsers = NULL; + interp->getargs.static_parsers = NULL; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 67bbbd01ca0c48..8170ffbadc8942 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -879,6 +879,8 @@ pycore_interp_init(PyThreadState *tstate) return _PyStatus_ERR("can't initialize warnings"); } + _PyArg_InitState(interp); + status = _PyAtExit_Init(interp); if (_PyStatus_EXCEPTION(status)) { return status; @@ -1875,7 +1877,6 @@ finalize_interp_clear(PyThreadState *tstate) if (is_main_interp) { _Py_HashRandomization_Fini(); - _PyArg_Fini(); _Py_ClearFileSystemEncoding(); _PyPerfTrampoline_Fini(); _PyPerfTrampoline_FreeArenas(); diff --git a/Python/pystate.c b/Python/pystate.c index 0832b37c278c76..193a272fd74674 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -864,6 +864,8 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) _PyWarnings_Fini(interp); _PyAtExit_Fini(interp); + _PyArg_Fini(interp); + // All Python types must be destroyed before the last GC collection. Python // types create a reference cycle to themselves in their in their // PyTypeObject.tp_mro member (the tuple contains the type).