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-108014: Add Py_IsFinalizing() function #108032

Merged
merged 5 commits into from
Aug 18, 2023
Merged
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
14 changes: 11 additions & 3 deletions Doc/c-api/init.rst
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,14 @@
:c:func:`Py_Initialize` is called again.


.. c:function:: int Py_IsFinalizing()
serhiy-storchaka marked this conversation as resolved.
Show resolved Hide resolved

Return non-zero if the Python interpreter is :term:`shutting down
<interpreter shutdown>`, return 0 otherwise.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this referring to the runtime (AKA main interpreter) or to the current interpreter? I'd expect it to be the current interpreter.

Would it make sense to explicitly pass an interpreter and use NULL to mean the current one (or main)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied the documentation of the sys.is_finalizing() function. If you want a different feature (pass an interpreter), I would prefer to have a different function.

It's set by Py_Finalize() which finalizes the main interpreter: other sub-interpreters should be deleted before explicitly, no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the doc to specify that we are talking about the main interpreter.

vstinner marked this conversation as resolved.
Show resolved Hide resolved

.. versionadded:: 3.13


.. c:function:: int Py_FinalizeEx()

Undo all initializations made by :c:func:`Py_Initialize` and subsequent use of
Expand Down Expand Up @@ -852,7 +860,7 @@
.. 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.

Expand All @@ -873,7 +881,7 @@
The following functions use thread-local storage, and are not compatible
with sub-interpreters:

.. c:function:: PyGILState_STATE PyGILState_Ensure()

Check warning on line 884 in Doc/c-api/init.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

c:identifier reference target not found: PyGILState_STATE

Ensure that the current thread is ready to call the Python C API regardless
of the current state of Python, or of the global interpreter lock. This may
Expand All @@ -898,11 +906,11 @@
.. 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.

.. c:function:: void PyGILState_Release(PyGILState_STATE)

Check warning on line 913 in Doc/c-api/init.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

c:identifier reference target not found: PyGILState_STATE

Release any resources previously acquired. After this call, Python's state will
be the same as it was prior to the corresponding :c:func:`PyGILState_Ensure` call
Expand Down Expand Up @@ -1014,7 +1022,7 @@
must be held.

.. versionchanged:: 3.9
This function now calls the :c:member:`PyThreadState.on_delete` callback.

Check warning on line 1025 in Doc/c-api/init.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

c:member reference target not found: PyThreadState.on_delete
Previously, that happened in :c:func:`PyThreadState_Delete`.


Expand Down Expand Up @@ -1180,7 +1188,7 @@
.. 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.

Expand Down Expand Up @@ -1639,7 +1647,7 @@

.. c:var:: int PyTrace_LINE

The value passed as the *what* parameter to a :c:type:`Py_tracefunc` function

Check warning on line 1650 in Doc/c-api/init.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

py:attr reference target not found: f_trace_lines
(but not a profiling function) when a line-number event is being reported.
It may be disabled for a frame by setting :attr:`f_trace_lines` to *0* on that frame.

Expand Down Expand Up @@ -1670,7 +1678,7 @@

.. c:var:: int PyTrace_OPCODE

The value for the *what* parameter to :c:type:`Py_tracefunc` functions (but not

Check warning on line 1681 in Doc/c-api/init.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

py:attr reference target not found: f_trace_opcodes
profiling functions) when a new opcode is about to be executed. This event is
not emitted by default: it must be explicitly requested by setting
:attr:`f_trace_opcodes` to *1* on the frame.
Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,10 @@ New Features
not needed.
(Contributed by Victor Stinner in :gh:`106004`.)

* Add :c:func:`Py_IsFinalizing` function: check if the Python interpreter is
vstinner marked this conversation as resolved.
Show resolved Hide resolved
:term:`shutting down <interpreter shutdown>`.
(Contributed by Victor Stinner in :gh:`108014`.)

Porting to Python 3.13
----------------------

Expand Down
2 changes: 2 additions & 0 deletions Include/cpython/pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 0 additions & 1 deletion Include/internal/pycore_pylifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add :c:func:`Py_IsFinalizing` function: check if the Python interpreter is
vstinner marked this conversation as resolved.
Show resolved Hide resolved
:term:`shutting down <interpreter shutdown>`. Patch by Victor Stinner.
2 changes: 1 addition & 1 deletion Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ _PyRuntime_Finalize(void)
}

int
_Py_IsFinalizing(void)
Py_IsFinalizing(void)
{
return _PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion Python/sysmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading