This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author stestagg
Recipients stestagg, xxm
Date 2020-12-29.15:02:36
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1609254156.76.0.536248442472.issue42763@roundup.psfhosted.org>
In-reply-to
Content
If we take your minimal example (that /sometimes/ crashes), and look at what python is doing:

import threading
t = threading.Thread(target=1, daemon=True).start()

---

The main thread does the following:

M1. Startup interpreter, parse code
M2. Import & execute threading module
M3. Create thread `T`, set target=1, set daemon=True
M4. Start thread
M5. Finalize local variables & state
M6. Terminate daemon threads
M7. Acquire IO lock to clean up IO
M8. Shutdown interpreter

Whereas the thread `T` does this:

T1. Startup
T2. Try to call target
T3. Realise that target is not callable & raise exception ('int' object is not callable)
T4. Acquire IO lock to print traceback
T5. Print traceback line 1
T6. Print traceback line n
T7. Release IO lock
T8. Shutdown thread


Now steps T1->T8 can happen *at any time* between M4 and M6.  But the moment M6 runs, the thread disappears without warning.

If the T4 step is run, then the daemon thread owns the IO lock, and must release it, but if step T7 doesn't run, then that lock is never released.

So in the case where you get a crash, the order is something like:

M1. M2. M3. M4.  T1. T2. T3. T4. T5. M5. [thread killed] M6. M7. <- Crash, because M7 can't acquire lock

But when there is no crash, the order is probably:

M1. M2. M3. M4.  T1. T2. T3. T4. T5. T6. T7. T8. M5. M6. M7. M8. <- No Crash because IO lock released in T7.

So you can see that this is the same fundamental thing as issue42717  (Where the shutdown during output was caused by spamming output repeatedly), but caused by a different route.

It might be possible to add handlers to the daemonic thread shutdown to clean up IO locks more cleanly?  But it's tricky, it seems like daemonic threads shutdown when they attempt to re-acquire the GIL after the interpreter has shutdown, so we're in pretty complex state management territory here.
History
Date User Action Args
2020-12-29 15:02:36stestaggsetrecipients: + stestagg, xxm
2020-12-29 15:02:36stestaggsetmessageid: <1609254156.76.0.536248442472.issue42763@roundup.psfhosted.org>
2020-12-29 15:02:36stestagglinkissue42763 messages
2020-12-29 15:02:36stestaggcreate