-
-
Notifications
You must be signed in to change notification settings - Fork 33k
Description
Bug report
Bug description:
The following short program will always run for 10 seconds on Windows, no matter how quickly you press ctrl+C.
from threading import Thread
import time
t = Thread(target=time.sleep, args=(10,))
t.start()
try:
print("Joining ...")
t.join()
print("Joined without exception")
except KeyboardInterrupt:
print("Keyboard interrupt")
The program does print "Keyboard interrupt", so the signal handler does actually get run and the exception gets thrown. It just doesn't interrupt the join. Indeed, if the thread function is changed to one that runs forever then this code would wait forever too.
The following expanded version, with a custom signal handler, shows that the signal handler is not run until the join()
completes. (As opposed to the possibility that it runs straight away, but then the join()
wait resumes before raising the exception. Unlikely I know.)
Version with custom signal handler
import signal
from threading import Thread
import time
start_time = time.monotonic()
def pr(s):
print(f"{time.monotonic() - start_time:.2f} {s}")
def sig_handler(signal, frame):
pr("Ctrl-C")
raise KeyboardInterrupt
signal.signal(signal.SIGINT, sig_handler)
t = Thread(target=time.sleep, args=(10,))
t.start()
try:
pr("Joining ...")
t.join()
pr("Joined without exception")
except KeyboardInterrupt:
pr("Keyboard interrupt")
If ctrl+c is pressed within 10 seconds then this prints:
0.00 Joining ...
10.00 Ctrl-C
10.00 Keyboard interrupt
Related issues:
- [Windows] KeyboardInterrupt during Thread.join hangs that Thread #66021 (bpo-21822) Sounds similar but is about
Thread.join()
not returning even after the thread is actually finished. In contrast, this issue is about wantingThread.join()
to complete before the thread is finished. - Race condition in Thread._wait_for_tstate_lock() #89437 (bpo-45274) This is about the same thing; the above issue was marked as a duplicate of this one.
- threading.Lock.acquire() not interruptible on Windows #74157 (bpo-29971) This looks like it's a similar bug but for a different call (
Lock.acquire()
rather thanThread.join()
. - pycore_condvar.h: remove Windows conditonal variable emulation, use Windows native conditional variable #89464 (bpo-45301 This is referenced from the above issues, but I'm not sure of the exact relationship.
One of the comments on #66021 is about this Thread.join()
rather than the real topic of that issue, but they are told "This is a different issue: bpo-29971. Currently, threading.Lock.acquire() cannot be interrupted by CTRL+C." This suggests to me that #74157 is very related to Thread.join()
not being interruptable. But it's not exactly the same ... because it's marked as fixed and this issue still persists.
CPython versions tested on:
3.10, 3.12
Operating systems tested on:
Windows