From 3ff5ef2ad3d89c3ccf4e07ac8fdd798267ae6c61 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 18 Aug 2023 12:34:41 +0200 Subject: [PATCH] gh-108014: Add Py_IsFinalizing() function (#108032) Co-authored-by: Serhiy Storchaka --- Doc/c-api/init.rst | 14 +++++++++++--- Doc/library/sys.rst | 4 ++-- Doc/whatsnew/3.13.rst | 4 ++++ Include/cpython/pylifecycle.h | 2 ++ Include/internal/pycore_pylifecycle.h | 1 - .../2023-08-16-17-16-19.gh-issue-108014.wXN3CF.rst | 2 ++ Modules/_asynciomodule.c | 2 +- Python/pylifecycle.c | 2 +- Python/sysmodule.c | 2 +- 9 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2023-08-16-17-16-19.gh-issue-108014.wXN3CF.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index dd53fe2bc95696..60f5c81cff572c 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -373,6 +373,14 @@ Initializing and finalizing the interpreter :c:func:`Py_Initialize` is called again. +.. c:function:: int Py_IsFinalizing() + + Return true (non-zero) if the main Python interpreter is + :term:`shutting down `. Return false (zero) otherwise. + + .. versionadded:: 3.13 + + .. c:function:: int Py_FinalizeEx() Undo all initializations made by :c:func:`Py_Initialize` and subsequent use of @@ -852,7 +860,7 @@ code, or when embedding the Python interpreter: .. note:: Calling this function from a thread when the runtime is finalizing will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`!_Py_IsFinalizing` or :func:`sys.is_finalizing` to + You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to check if the interpreter is in process of being finalized before calling this function to avoid unwanted termination. @@ -898,7 +906,7 @@ with sub-interpreters: .. note:: Calling this function from a thread when the runtime is finalizing will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`!_Py_IsFinalizing` or :func:`sys.is_finalizing` to + You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to check if the interpreter is in process of being finalized before calling this function to avoid unwanted termination. @@ -1180,7 +1188,7 @@ All of the following functions must be called after :c:func:`Py_Initialize`. .. note:: Calling this function from a thread when the runtime is finalizing will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`!_Py_IsFinalizing` or :func:`sys.is_finalizing` to + You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to check if the interpreter is in process of being finalized before calling this function to avoid unwanted termination. diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index b6346bafbf625e..da2435aa4bc23d 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -1121,8 +1121,8 @@ always available. .. function:: is_finalizing() - Return :const:`True` if the Python interpreter is - :term:`shutting down `, :const:`False` otherwise. + Return :const:`True` if the main Python interpreter is + :term:`shutting down `. Return :const:`False` otherwise. .. versionadded:: 3.5 diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 13ae6e595dc993..85aa81b4a98d2c 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -832,6 +832,10 @@ New Features not needed. (Contributed by Victor Stinner in :gh:`106004`.) +* Add :c:func:`Py_IsFinalizing` function: check if the main Python interpreter is + :term:`shutting down `. + (Contributed by Victor Stinner in :gh:`108014`.) + Porting to Python 3.13 ---------------------- diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index d425a233f71000..11b280afa8435b 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -81,3 +81,5 @@ PyAPI_FUNC(PyStatus) Py_NewInterpreterFromConfig( typedef void (*atexit_datacallbackfunc)(void *); PyAPI_FUNC(int) PyUnstable_AtExit( PyInterpreterState *, atexit_datacallbackfunc, void *); + +PyAPI_FUNC(int) Py_IsFinalizing(void); diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index b4d5b1f1239e1d..56abd57d2bd5cf 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -98,7 +98,6 @@ extern int _Py_FdIsInteractive(FILE *fp, PyObject *filename); extern const char* _Py_gitidentifier(void); extern const char* _Py_gitversion(void); -extern int _Py_IsFinalizing(void); PyAPI_FUNC(int) _Py_IsInterpreterFinalizing(PyInterpreterState *interp); /* Random */ diff --git a/Misc/NEWS.d/next/C API/2023-08-16-17-16-19.gh-issue-108014.wXN3CF.rst b/Misc/NEWS.d/next/C API/2023-08-16-17-16-19.gh-issue-108014.wXN3CF.rst new file mode 100644 index 00000000000000..fee3d5b941dc8d --- /dev/null +++ b/Misc/NEWS.d/next/C API/2023-08-16-17-16-19.gh-issue-108014.wXN3CF.rst @@ -0,0 +1,2 @@ +Add :c:func:`Py_IsFinalizing` function: check if the main Python interpreter is +:term:`shutting down `. Patch by Victor Stinner. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 39c803355ba95b..6266dc8e3555f8 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -529,7 +529,7 @@ future_init(FutureObj *fut, PyObject *loop) } if (is_true && !_Py_IsInterpreterFinalizing(_PyInterpreterState_GET())) { /* Only try to capture the traceback if the interpreter is not being - finalized. The original motivation to add a `_Py_IsFinalizing()` + finalized. The original motivation to add a `Py_IsFinalizing()` call was to prevent SIGSEGV when a Future is created in a __del__ method, which is called during the interpreter shutdown and the traceback module is already unloaded. diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 90633960cb00ee..263ead39fa472a 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -129,7 +129,7 @@ _PyRuntime_Finalize(void) } int -_Py_IsFinalizing(void) +Py_IsFinalizing(void) { return _PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index f82901181f8866..54533603f1a7f8 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -2095,7 +2095,7 @@ static PyObject * sys_is_finalizing_impl(PyObject *module) /*[clinic end generated code: output=735b5ff7962ab281 input=f0df747a039948a5]*/ { - return PyBool_FromLong(_Py_IsFinalizing()); + return PyBool_FromLong(Py_IsFinalizing()); } #ifdef Py_STATS