Skip to content

Commit 2f33cd8

Browse files
committed
gh-114570: Add PythonFinalizationError exception
Add PythonFinalizationError exception. This exception derived from RuntimeError is raised when an operation is blocked during the Python finalization. The following functions now raise PythonFinalizationError, instead of RuntimeError: * _thread.start_new_thread() * subprocess.Popen * os.fork() * os.fork1() * os.forkpty() Morever, _winapi.Overlapped finalizer now logs an unraisable PythonFinalizationError, instead of an unraisable RuntimeError.
1 parent 326119d commit 2f33cd8

File tree

13 files changed

+55
-6
lines changed

13 files changed

+55
-6
lines changed

Doc/library/exceptions.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,24 @@ The following exceptions are the exceptions that are usually raised.
416416
handling in C, most floating point operations are not checked.
417417

418418

419+
.. exception:: PythonFinalizationError
420+
421+
This exception is derived from :exc:`RuntimeError`. It is raised when
422+
an operations is blocked during the :term:`Python finalization <interpreter
423+
shutdown>`.
424+
425+
Examples of operations which can be blocked with a
426+
:exc:`PythonFinalizationError` during the Python finalization:
427+
428+
* create a new Python thread;
429+
* :func:`os.fork`.
430+
431+
See also the :func:`sys.is_finalizing` function.
432+
433+
.. versionadded:: 3.13
434+
Previously, a plain :exc:`RuntimeError` was raised.
435+
436+
419437
.. exception:: RecursionError
420438

421439
This exception is derived from :exc:`RuntimeError`. It is raised when the

Doc/library/sys.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,8 @@ always available.
12021202
Return :const:`True` if the main Python interpreter is
12031203
:term:`shutting down <interpreter shutdown>`. Return :const:`False` otherwise.
12041204

1205+
See also the :exc:`PythonFinalizationError` exception.
1206+
12051207
.. versionadded:: 3.5
12061208

12071209
.. data:: last_exc

Doc/whatsnew/3.13.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,21 @@ Other Language Changes
160160
(Contributed by Levi Sabah, Zackery Spytz and Hugo van Kemenade in
161161
:gh:`73965`.)
162162

163+
* Add :exc:`PythonFinalizationError` exception. This exception derived from
164+
:exc:`RuntimeError` is raised when an operation is blocked during
165+
the :term:`Python finalization <interpreter shutdown>`.
166+
167+
The following functions now raise PythonFinalizationError, instead of
168+
:exc:`RuntimeError`:
169+
170+
* :func:`_thread.start_new_thread`.
171+
* :class:`subprocess.Popen`.
172+
* :func:`os.fork`.
173+
* :func:`os.forkpty`.
174+
175+
(Contributed by Victor Stinner in :gh:`114570`.)
176+
177+
163178
New Modules
164179
===========
165180

Include/cpython/pyerrors.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,6 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc(
122122

123123
PyAPI_FUNC(void) PyErr_FormatUnraisable(const char *, ...);
124124

125+
PyAPI_DATA(PyObject *) PyExc_PythonFinalizationError;
126+
125127
#define Py_FatalError(message) _Py_FatalErrorFunc(__func__, (message))

Lib/test/exception_hierarchy.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ BaseException
4040
├── ReferenceError
4141
├── RuntimeError
4242
│ ├── NotImplementedError
43+
│ ├── PythonFinalizationError
4344
│ └── RecursionError
4445
├── StopAsyncIteration
4546
├── StopIteration

Lib/test/test_pickle.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ def test_exceptions(self):
564564
if exc in (BlockingIOError,
565565
ResourceWarning,
566566
StopAsyncIteration,
567+
PythonFinalizationError,
567568
RecursionError,
568569
EncodingWarning,
569570
BaseExceptionGroup,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add :exc:`PythonFinalizationError` exception. This exception derived from
2+
:exc:`RuntimeError` is raised when an operation is blocked during the
3+
:term:`Python finalization <interpreter shutdown>`. Patch by Victor Stinner.

Modules/_posixsubprocess.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args,
10321032

10331033
PyInterpreterState *interp = _PyInterpreterState_GET();
10341034
if ((preexec_fn != Py_None) && interp->finalizing) {
1035-
PyErr_SetString(PyExc_RuntimeError,
1035+
PyErr_SetString(PyExc_PythonFinalizationError,
10361036
"preexec_fn not supported at interpreter shutdown");
10371037
return NULL;
10381038
}

Modules/_threadmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,7 @@ do_start_new_thread(thread_module_state* state,
13041304
return -1;
13051305
}
13061306
if (interp->finalizing) {
1307-
PyErr_SetString(PyExc_RuntimeError,
1307+
PyErr_SetString(PyExc_PythonFinalizationError,
13081308
"can't create new thread at interpreter shutdown");
13091309
return -1;
13101310
}

Modules/_winapi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ overlapped_dealloc(OverlappedObject *self)
139139
{
140140
/* The operation is still pending -- give a warning. This
141141
will probably only happen on Windows XP. */
142-
PyErr_SetString(PyExc_RuntimeError,
142+
PyErr_SetString(PyExc_PythonFinalizationError,
143143
"I/O operations still in flight while destroying "
144144
"Overlapped object, the process may crash");
145145
PyErr_WriteUnraisable(NULL);

0 commit comments

Comments
 (0)