8000 gh-120838: Disallow Py_Finalize() if Py_RunMain() is Running by ericsnowcurrently · Pull Request #120841 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-120838: Disallow Py_Finalize() if Py_RunMain() is Running #120841

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Disallow Py_Finalize() if Py_RunMain() is running.
  • Loading branch information
ericsnowcurrently committed Jun 21, 2024
commit 1aab105ba8d9c9f85c245159e31afe48fb3c861f
2 changes: 2 additions & 0 deletions Include/internal/pycore_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ typedef struct pyruntimestate {
unsigned long main_thread;
PyThreadState *main_tstate;

int is_pymain;

/* ---------- IMPORTANT ---------------------------
The fields above this line are declared as early as
possible to facilitate out-of-process observability
Expand Down
8 changes: 7 additions & 1 deletion Modules/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -711,19 +711,25 @@ pymain_exit_error(PyStatus status)
}


extern int _Py_FinalizeMain(void);

int
Py_RunMain(void)
{
int exitcode = 0;

_PyRuntime.is_pymain = 1;

pymain_run_python(&exitcode);

if (Py_FinalizeEx() < 0) {
if (_Py_FinalizeMain() < 0) {
/* Value unlikely to be confused with a non-error exit status or
other special meaning */
exitcode = 120;
}

_PyRuntime.is_pymain = 0;

pymain_free();

if (_PyRuntime.signals.unhandled_keyboard_interrupt) {
Expand Down
33 changes: 29 additions & 4 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1909,18 +1909,25 @@ finalize_interp_delete(PyInterpreterState *interp)
}


int
Py_FinalizeEx(void)
static int
_Py_Finalize(_PyRuntimeState *runtime, const char *not_pymain)
{
int status = 0;

_PyRuntimeState *runtime = &_PyRuntime;
if (!runtime->initialized) {
return status;
}

if (not_pymain && runtime->is_pymain) {
fprintf(stderr,
"%s() should not be called while Py_RunMain() is running",
not_pymain);
return 1;
}

/* Get current thread state and interpreter pointer */
PyThreadState *tstate = _PyThreadState_GET();
assert(tstate->interp->runtime == runtime);
// XXX assert(_Py_IsMainInterpreter(tstate->interp));
// XXX assert(_Py_IsMainThread());

Expand Down Expand Up @@ -2142,10 +2149,28 @@ Py_FinalizeEx(void)
return status;
}

/* _Py_FinalizeMain() is used exclusively by Py_RunMain(). */
int
_Py_FinalizeMain(void)
{
_PyRuntimeState *runtime = &_PyRuntime;
assert(runtime->is_pymain);
assert(_Py_IsMainInterpreter(_PyInterpreterState_GET()));
assert(_Py_IsMainThread());
assert(_PyThreadState_GET() == runtime->main_tstate);
return _Py_Finalize(runtime, NULL);
}

int
Py_FinalizeEx(void)
{
return _Py_Finalize(&_PyRuntime, "Py_FinalizeEx");
}

void
Py_Finalize(void)
{
Py_FinalizeEx();
(void)_Py_Finalize(&_PyRuntime, "Py_Finalize");
}


Expand Down
0