Message289913
It turns out that this bug is more general than signal.pause, and has caused problems for a few different people:
https://github.com/dabeaz/curio/issues/118#issuecomment-287735781
https://github.com/dabeaz/curio/issues/118#issuecomment-287798241
https://github.com/dabeaz/curio/issues/118#issuecomment-287887843
The basic problem is that CPython's signal handling strategy on Unix-likes assumes that if a signal is delivered to the process at a time when the main thread is blocked in a syscall, then that syscall will promptly exit with EINTR. So for example, time.sleep has some clever code on Windows to make it interruptible with control-C, but on Unix we assume that the kernel will break the sleep for us.
The problem with this is that POSIX only guarantees that *some* thread will receive the signal -- not necessarily the main thread. In practice it seems like most implementations do deliver most signals to the main thread or CPython wouldn't have gotten away with this for as long as it has, but in particular it seems like Linux is happy to deliver SIGCHLD to random other threads. So the C-level signal handler runs in whatever thread, it sets the flag for the main thread to run the Python-level signal handler... and then the main thread sits there blocked in sleep() or select() or pause() or whatever, and never checks the flag.
A simple solution would be to make sure signals are always delivered to the main thread, by adjusting the C-level signal handler to do something like:
if (current_thread != main_thread) {
pthread_kill(main_thread, sig_num);
return;
} |
|
Date |
User |
Action |
Args |
2017-03-21 04:53:36 | njs | set | recipients:
+ njs, vstinner, neologix, bkabrda |
2017-03-21 04:53:36 | njs | set | messageid: <1490072016.58.0.666635391633.issue21895@psf.upfronthosting.co.za> |
2017-03-21 04:53:36 | njs | link | issue21895 messages |
2017-03-21 04:53:35 | njs | create | |
|