summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/exceptions.rst18
-rw-r--r--Doc/library/sys.rst2
-rw-r--r--Doc/whatsnew/3.13.rst15
-rw-r--r--Include/cpython/pyerrors.h2
-rw-r--r--Lib/test/exception_hierarchy.txt1
-rw-r--r--Lib/test/test_pickle.py1
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2024-02-12-17-18-26.gh-issue-114570.BzwMlJ.rst3
-rw-r--r--Modules/_posixsubprocess.c2
-rw-r--r--Modules/_threadmodule.c2
-rw-r--r--Modules/_winapi.c2
-rw-r--r--Modules/posixmodule.c6
-rw-r--r--Objects/exceptions.c5
-rw-r--r--Tools/c-analyzer/cpython/globals-to-fix.tsv2
13 files changed, 55 insertions, 6 deletions
diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst
index 3191315..88417b4 100644
--- a/Doc/library/exceptions.rst
+++ b/Doc/library/exceptions.rst
@@ -416,6 +416,24 @@ The following exceptions are the exceptions that are usually raised.
handling in C, most floating point operations are not checked.
+.. exception:: PythonFinalizationError
+
+ This exception is derived from :exc:`RuntimeError`. It is raised when
+ an operation is blocked during interpreter shutdown also known as
+ :term:`Python finalization <interpreter shutdown>`.
+
+ Examples of operations which can be blocked with a
+ :exc:`PythonFinalizationError` during the Python finalization:
+
+ * Creating a new Python thread.
+ * :func:`os.fork`.
+
+ See also the :func:`sys.is_finalizing` function.
+
+ .. versionadded:: 3.13
+ Previously, a plain :exc:`RuntimeError` was raised.
+
+
.. exception:: RecursionError
This exception is derived from :exc:`RuntimeError`. It is raised when the
diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst
index ad8857f..351c44b 100644
--- a/Doc/library/sys.rst
+++ b/Doc/library/sys.rst
@@ -1202,6 +1202,8 @@ always available.
Return :const:`True` if the main Python interpreter is
:term:`shutting down <interpreter shutdown>`. Return :const:`False` otherwise.
+ See also the :exc:`PythonFinalizationError` exception.
+
.. versionadded:: 3.5
.. data:: last_exc
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index b14fb4e..1e07641 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -160,6 +160,21 @@ Other Language Changes
(Contributed by Levi Sabah, Zackery Spytz and Hugo van Kemenade in
:gh:`73965`.)
+* Add :exc:`PythonFinalizationError` exception. This exception derived from
+ :exc:`RuntimeError` is raised when an operation is blocked during
+ the :term:`Python finalization <interpreter shutdown>`.
+
+ The following functions now raise PythonFinalizationError, instead of
+ :exc:`RuntimeError`:
+
+ * :func:`_thread.start_new_thread`.
+ * :class:`subprocess.Popen`.
+ * :func:`os.fork`.
+ * :func:`os.forkpty`.
+
+ (Contributed by Victor Stinner in :gh:`114570`.)
+
+
New Modules
===========
diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h
index 479b908..32c5884 100644
--- a/Include/cpython/pyerrors.h
+++ b/Include/cpython/pyerrors.h
@@ -122,4 +122,6 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc(
PyAPI_FUNC(void) PyErr_FormatUnraisable(const char *, ...);
+PyAPI_DATA(PyObject *) PyExc_PythonFinalizationError;
+
#define Py_FatalError(message) _Py_FatalErrorFunc(__func__, (message))
diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt
index 217ee15..65f5485 100644
--- a/Lib/test/exception_hierarchy.txt
+++ b/Lib/test/exception_hierarchy.txt
@@ -40,6 +40,7 @@ BaseException
├── ReferenceError
├── RuntimeError
│ ├── NotImplementedError
+ │ ├── PythonFinalizationError
│ └── RecursionError
├── StopAsyncIteration
├── StopIteration
diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py
index 5e187e5..19f9779 100644
--- a/Lib/test/test_pickle.py
+++ b/Lib/test/test_pickle.py
@@ -564,6 +564,7 @@ class CompatPickleTests(unittest.TestCase):
if exc in (BlockingIOError,
ResourceWarning,
StopAsyncIteration,
+ PythonFinalizationError,
RecursionError,
EncodingWarning,
BaseExceptionGroup,
diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-02-12-17-18-26.gh-issue-114570.BzwMlJ.rst b/Misc/NEWS.d/next/Core and Builtins/2024-02-12-17-18-26.gh-issue-114570.BzwMlJ.rst
new file mode 100644
index 0000000..828d47d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2024-02-12-17-18-26.gh-issue-114570.BzwMlJ.rst
@@ -0,0 +1,3 @@
+Add :exc:`PythonFinalizationError` exception. This exception derived from
+:exc:`RuntimeError` is raised when an operation is blocked during the
+:term:`Python finalization <interpreter shutdown>`. Patch by Victor Stinner.
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index aa1a300..bcbbe70 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -1032,7 +1032,7 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args,
PyInterpreterState *interp = _PyInterpreterState_GET();
if ((preexec_fn != Py_None) && interp->finalizing) {
- PyErr_SetString(PyExc_RuntimeError,
+ PyErr_SetString(PyExc_PythonFinalizationError,
"preexec_fn not supported at interpreter shutdown");
return NULL;
}
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index d7840ea..da6a8bc 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -1304,7 +1304,7 @@ do_start_new_thread(thread_module_state* state,
return -1;
}
if (interp->finalizing) {
- PyErr_SetString(PyExc_RuntimeError,
+ PyErr_SetString(PyExc_PythonFinalizationError,
"can't create new thread at interpreter shutdown");
return -1;
}
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index 83a4ccd..8f9b852 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -139,7 +139,7 @@ overlapped_dealloc(OverlappedObject *self)
{
/* The operation is still pending -- give a warning. This
will probably only happen on Windows XP. */
- PyErr_SetString(PyExc_RuntimeError,
+ PyErr_SetString(PyExc_PythonFinalizationError,
"I/O operations still in flight while destroying "
"Overlapped object, the process may crash");
PyErr_WriteUnraisable(NULL);
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index ef6d656..958b5a5 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -7841,7 +7841,7 @@ os_fork1_impl(PyObject *module)
PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->finalizing) {
- PyErr_SetString(PyExc_RuntimeError,
+ PyErr_SetString(PyExc_PythonFinalizationError,
"can't fork at interpreter shutdown");
return NULL;
}
@@ -7885,7 +7885,7 @@ os_fork_impl(PyObject *module)
pid_t pid;
PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->finalizing) {
- PyErr_SetString(PyExc_RuntimeError,
+ PyErr_SetString(PyExc_PythonFinalizationError,
"can't fork at interpreter shutdown");
return NULL;
}
@@ -8718,7 +8718,7 @@ os_forkpty_impl(PyObject *module)
PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->finalizing) {
- PyErr_SetString(PyExc_RuntimeError,
+ PyErr_SetString(PyExc_PythonFinalizationError,
"can't fork at interpreter shutdown");
return NULL;
}
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 3df3a9b..63c461d 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -2177,6 +2177,10 @@ SimpleExtendsException(PyExc_Exception, RuntimeError,
SimpleExtendsException(PyExc_RuntimeError, RecursionError,
"Recursion limit exceeded.");
+// PythonFinalizationError extends RuntimeError
+SimpleExtendsException(PyExc_RuntimeError, PythonFinalizationError,
+ "Operation blocked during Python finalization.");
+
/*
* NotImplementedError extends RuntimeError
*/
@@ -3641,6 +3645,7 @@ static struct static_exception static_exceptions[] = {
ITEM(KeyError), // base: LookupError(Exception)
ITEM(ModuleNotFoundError), // base: ImportError(Exception)
ITEM(NotImplementedError), // base: RuntimeError(Exception)
+ ITEM(PythonFinalizationError), // base: RuntimeError(Exception)
ITEM(RecursionError), // base: RuntimeError(Exception)
ITEM(UnboundLocalError), // base: NameError(Exception)
ITEM(UnicodeError), // base: ValueError(Exception)
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index 5c5016f..4511966 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -189,6 +189,7 @@ Objects/exceptions.c - _PyExc_ProcessLookupError -
Objects/exceptions.c - _PyExc_TimeoutError -
Objects/exceptions.c - _PyExc_EOFError -
Objects/exceptions.c - _PyExc_RuntimeError -
+Objects/exceptions.c - _PyExc_PythonFinalizationError -
Objects/exceptions.c - _PyExc_RecursionError -
Objects/exceptions.c - _PyExc_NotImplementedError -
Objects/exceptions.c - _PyExc_NameError -
@@ -254,6 +255,7 @@ Objects/exceptions.c - PyExc_ProcessLookupError -
Objects/exceptions.c - PyExc_TimeoutError -
Objects/exceptions.c - PyExc_EOFError -
Objects/exceptions.c - PyExc_RuntimeError -
+Objects/exceptions.c - PyExc_PythonFinalizationError -
Objects/exceptions.c - PyExc_RecursionError -
Objects/exceptions.c - PyExc_NotImplementedError -
Objects/exceptions.c - PyExc_NameError -