Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-119213: Fix getargs.c to store state in InterpreterState... #119195

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Include/internal/pycore_interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion Include/internal/pycore_pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 0 additions & 5 deletions Include/internal/pycore_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down
18 changes: 13 additions & 5 deletions Python/getargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *, ...);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
3 changes: 2 additions & 1 deletion Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1875,7 +1877,6 @@ finalize_interp_clear(PyThreadState *tstate)

if (is_main_interp) {
_Py_HashRandomization_Fini();
_PyArg_Fini();
_Py_ClearFileSystemEncoding();
_PyPerfTrampoline_Fini();
_PyPerfTrampoline_FreeArenas();
Expand Down
2 changes: 2 additions & 0 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
Loading