| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| Expand Up | @@ -1171,6 +1171,41 @@ def __del__(self): | |
| self.assertEqual(out.strip(), b"OK") | ||
| self.assertIn(b"can't create new thread at interpreter shutdown", err) | ||
|
|
||
| @unittest.skipIf(support.Py_GIL_DISABLED, "gh-124149: daemon threads don't force exit") | ||
| def test_join_force_terminated_daemon_thread_in_finalization(self): | ||
| # gh-123940: Py_Finalize() forces all daemon threads to exit | ||
| # immediately (without unwinding the stack) upon acquiring the | ||
| # GIL. Finalizers that run after this must be able to join the daemon | ||
| # threads that were forced to exit. | ||
| code = textwrap.dedent(""" | ||
| import threading | ||
|
|
||
|
|
||
| def loop(): | ||
| while True: | ||
| pass | ||
|
Comment thread
Comment on lines
+1184
to
+1186
Copy link
Copy Markdown
Contributor
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. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityA slight variant where loop() calls time.sleep(1) hard crashes in 3.11 and 3.12. I'm not sure what to make of that, other than this sort of behavior wasn't robust previously either. I think it's noteworthy that the change that led to the issue was from just a few days ago -- it doesn't look like it was some longstanding code that just broke now.
Sorry, something went wrong.
gpshead reacted with thumbs up emoji
All reactions
Copy link
Copy Markdown
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. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Qualitypossibly #87135 related.
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
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. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityThis is the issue #116514 colesbury linked when I asked (I wasn't able to repro just the time.sleep variant mentioned here)
Sorry, something went wrong.
All reactions
|
||
|
|
||
|
|
||
| class Cycle: | ||
| def __init__(self): | ||
| self.self_ref = self | ||
| self.thr = threading.Thread(target=loop, daemon=True) | ||
| self.thr.start() | ||
|
|
||
| def __del__(self): | ||
| self.thr.join() | ||
|
Comment thread
mpage marked this conversation as resolved.
|
||
| print('__del__ called') | ||
|
|
||
| # Cycle holds a reference to itself, which ensures it is cleaned | ||
| # up during the GC that runs after daemon threads have been | ||
| # forced to exit during finalization. | ||
| Cycle() | ||
| """) | ||
| rc, out, err = assert_python_ok("-c", code) | ||
| self.assertEqual(err, b"") | ||
| self.assertIn(b"__del__ called", out) | ||
|
|
||
|
|
||
| class ThreadJoinOnShutdown(BaseTestCase): | ||
|
|
||
| def _run_and_join(self, script): | ||
| Expand Down | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| Expand Up | @@ -665,6 +665,8 @@ init_interpreter(PyInterpreterState *interp, | |
| /* Fix the self-referential, statically initialized fields. */ | ||
| interp->dtoa = (struct _dtoa_state)_dtoa_state_INIT(interp); | ||
| } | ||
| llist_init(&interp->threads.daemon_handles); | ||
| llist_init(&interp->threads.non_daemon_handles); | ||
|
Comment thread
Comment on lines
+668
to
+669
Copy link
Copy Markdown
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. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityIt would make sense to have a _PyThread_InitThreadHandles() for this, to match _PyThread_ClearThreadHandles().
Sorry, something went wrong.
mpage reacted with thumbs up emoji
All reactions
|
||
|
|
||
| interp->_initialized = 1; | ||
| return _PyStatus_OK(); | ||
| Expand Down Expand Up | @@ -811,7 +813,7 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) | |
| // XXX Eliminate the need to do this. | ||
| tstate->_status.cleared = 0; | ||
| } | ||
|
|
||
| _PyThread_ClearThreadHandles(interp); | ||
| #ifdef _Py_TIER2 | ||
| _PyOptimizerObject *old = _Py_SetOptimizer(interp, NULL); | ||
| assert(old != NULL); | ||
| Expand Down | ||
| Back | FazBrowse Home | New Git URL |
Uh oh!
There was an error while loading. Please reload this page.