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

_Py_IsFinalizing has been removed, meaning C/C++ threads cannot avoid termination during shutdown #108014

Closed
2 tasks done
dgrisby opened this issue Aug 16, 2023 · 7 comments
Closed
2 tasks done
Labels
topic-C-API type-bug An unexpected behavior, bug, or error

Comments

@dgrisby
Copy link
Contributor

dgrisby commented Aug 16, 2023

Checklist

  • I am confident this is a bug in CPython, not a bug in a third-party project
  • I have searched the CPython issue tracker,
    and am confident this bug has not been reported before

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

Python 3.13.0a0 (main, Jul 29 2023, 00:25:05) [GCC 13.1.1 20230614 (Red Hat 13.1.1-4)]

A clear and concise description of the bug:

Threads that call PyEval_RestoreThread while the runtime is finalizing are terminated. The documented way to avoid this is to call _Py_IsFinalizing() to check. https://docs.python.org/3.13/c-api/init.html#c.PyEval_RestoreThread

_Py_IsFinalizing() has been removed from Python 3.13. Please provide a public API function that has the equivalent behavior, or some other way for a non-Python thread to safely attempt to call into Python code when the interpreter may be finalizing.

Rather than the calling code checking for finalization, an alternative solution would be to provide a variant of PyEval_RestoreThread that returns success or failure, so the calling code can know that it was unable to acquire the GIL, and react accordingly.

Linked PRs

@dgrisby dgrisby added the type-bug An unexpected behavior, bug, or error label Aug 16, 2023
@vstinner
Copy link
Member

Since sys.is_finalizing() was added to Python 3.5, IMO it's fine to add a public C API function for that: https://docs.python.org/dev/library/sys.html#sys.is_finalizing

cc @ericsnowcurrently

@ericsnowcurrently
Copy link
Member

FYI, there is some work to hang remaining threads rather than killing them: gh-105805. I expect that would land in 3.13.
Presumably a Py_IsFinalizing() would still be helpful though.

@erlend-aasland
Copy link
Contributor

erlend-aasland commented Aug 17, 2023

I think it would make sense to also make _Py_IsInterpreterFinalizing public:

cpython/Python/pylifecycle.c

Lines 2181 to 2191 in 1344cfa

int
_Py_IsInterpreterFinalizing(PyInterpreterState *interp)
{
/* We check the runtime first since, in a daemon thread,
interp might be dangling pointer. */
PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(&_PyRuntime);
if (finalizing == NULL) {
finalizing = _PyInterpreterState_GetFinalizing(interp);
}
return finalizing != NULL;
}

vstinner added a commit that referenced this issue Aug 18, 2023
@vstinner
Copy link
Member

Function added by commit 3ff5ef2.

@vstinner
Copy link
Member

Function added to pythoncapi-compat by commit python/pythoncapi-compat@1bb4e16.

@vstinner
Copy link
Member

I proposed adding PythonFinalizationError exception in PR gh-109809.

@vstinner
Copy link
Member

vstinner commented Oct 5, 2023

Follow-up: @wjakob asks to add this new function to the limited C API version 3.13.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-C-API type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

5 participants