-
-
Notifications
You must be signed in to change notification settings - Fork 34.5k
gh-136003: Execute pre-finalization callbacks in a loop #136004
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
Changes from 1 commit
354e6b5
3090524
43038b8
8d4151c
add4d33
3edc3a8
ec57918
970153b
cfd62b8
859070f
37098a0
8a1aa13
cbcd552
54613a1
9ccdb5f
9cd75b7
1360059
475538a
a794188
2dda7a4
f1460af
1e1301d
51a20d4
cf2dc1e
6ea3792
8c12e6c
8b87014
e57bfde
e202848
0e66c88
c8cac69
2ab28b0
c9d5f4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,7 +96,7 @@ static PyStatus init_android_streams(PyThreadState *tstate); | |
| #if defined(__APPLE__) && HAS_APPLE_SYSTEM_LOG | ||
| static PyStatus init_apple_streams(PyThreadState *tstate); | ||
| #endif | ||
| static int wait_for_thread_shutdown(PyThreadState *tstate); | ||
| static void wait_for_thread_shutdown(PyThreadState *tstate); | ||
| static void finalize_subinterpreters(void); | ||
| static void call_ll_exitfuncs(_PyRuntimeState *runtime); | ||
|
|
||
|
|
@@ -2010,15 +2010,11 @@ make_pre_finalization_calls(PyThreadState *tstate) | |
| * could start a thread or vice versa. To ensure that we properly clean | ||
| * call everything, we run these in a loop until none of them run anything. */ | ||
| for (;;) { | ||
| int called = 0; | ||
|
|
||
| // Wrap up existing "threading"-module-created, non-daemon threads. | ||
| int threads_joined = wait_for_thread_shutdown(tstate); | ||
| called = Py_MAX(called, threads_joined); | ||
| wait_for_thread_shutdown(tstate); | ||
|
Comment on lines
+2085
to
+2086
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't necessarily need to worry about it here, but it would probably also be worth waiting here for the interpreter to not be "running main".
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's do that in a follow-up (probably tomorrow). |
||
|
|
||
| // Make any remaining pending calls. | ||
| int made_pending_calls = _Py_FinishPendingCalls(tstate); | ||
| called = Py_MAX(called, made_pending_calls); | ||
| _Py_FinishPendingCalls(tstate); | ||
|
|
||
| /* The interpreter is still entirely intact at this point, and the | ||
| * exit funcs may be relying on that. In particular, if some thread | ||
|
|
@@ -2030,9 +2026,9 @@ make_pre_finalization_calls(PyThreadState *tstate) | |
| * the threads created via Threading. | ||
| */ | ||
|
|
||
| int called_atexit = _PyAtExit_Call(tstate->interp); | ||
| called = Py_MAX(called, called_atexit); | ||
| _PyAtExit_Call(tstate->interp); | ||
|
|
||
| _PyRWMutex_Unlock(&tstate->interp->prefini_mutex); | ||
| if (called == 0) { | ||
| break; | ||
| } | ||
|
|
@@ -3456,7 +3452,7 @@ Py_ExitStatusException(PyStatus status) | |
| the threading module was imported in the first place. | ||
| The shutdown routine will wait until all non-daemon | ||
| "threading" threads have completed. */ | ||
| static int | ||
| static void | ||
| wait_for_thread_shutdown(PyThreadState *tstate) | ||
| { | ||
| PyObject *result; | ||
|
|
@@ -3466,19 +3462,16 @@ wait_for_thread_shutdown(PyThreadState *tstate) | |
| PyErr_FormatUnraisable("Exception ignored on threading shutdown"); | ||
| } | ||
| /* else: threading not imported */ | ||
| return 0; | ||
| return; | ||
| } | ||
| int called = 0; | ||
| result = PyObject_CallMethodNoArgs(threading, &_Py_ID(_shutdown)); | ||
| if (result == NULL) { | ||
| PyErr_FormatUnraisable("Exception ignored on threading shutdown"); | ||
| } | ||
| else { | ||
| assert(PyBool_Check(result) && _Py_IsImmortal(result)); | ||
| called = result == Py_True; | ||
| } | ||
| Py_XDECREF(result); | ||
| Py_DECREF(threading); | ||
| return called; | ||
| return; | ||
| } | ||
|
|
||
| int Py_AtExit(void (*func)(void)) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to add an arbitrary limit to detect infinite loop? For example, log an error after 16 attemps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it would prevent deadlocks in rare cases, but it would cause crashes in other equally rare cases. Maybe it would be better to emit a fatal error when there are too many iterations?