[issue12187] subprocess.wait() with a timeout uses polling on POSIX
STINNER Victor
report at bugs.python.org
Thu Jun 9 00:29:00 CEST 2011
STINNER Victor <victor.stinner at haypocalc.com> added the comment:
> To be portable, we would need to ...
Antoine is right: we don't have to be portable. We can write an "optimized" implementations (without polling) for a specific OS, even for a specific version of an OS (e.g. like Linux kernel >= 2.6.22 for signalfd).
I like the idea of signalfd(), but I don't know exactly how it works. Should we block the signal? What happens when we unblock the signal? It would be nice if the signal handler is called on unblock, because it would not change the current behaviour. Is it possible to block a signal in all threads? pthread_sigmask() blocks signals in the current thread, the manual page of sigprocmask() has a funny comment: "The use of sigprocmask() is unspecified in a multithreaded process; see pthread_sigmask(3)."
Extract of signalfd() manual page: "Normally, the set of signals to be received via the file descriptor should be blocked using sigprocmask(2), to prevent the signals being handled according to their default dispositions."
Is SIGCHLD only raised once at child process exit? "SIGCLD would be delivered constantly (unless blocked) while any child is ready to be waited for." according to http://lwn.net/Articles/414618/
> There's just one problem: SIGCHLD is ignored by default,
> which means that sigwait and friends won't return when a child exits.
sigwait() is not impacted by the associated signal handler, but sigwait() only works if the signal is blocked (e.g. by pthread_sigmask):
"If no signal in set is pending at the time of the call, the thread is suspended until one or more becomes pending. The signals defined by set will been blocked at the time of the call to sigwait(); otherwise the behaviour is undefined."
http://pubs.opengroup.org/onlinepubs/007908799/xsh/sigwait.html
Example (for Python 3.3):
--------------------------
from signal import *
import subprocess
signum = SIGCHLD
process = subprocess.Popen("sleep 1", shell=True)
print("Wait %s..." % signum)
pthread_sigmask(SIG_BLOCK, [signum])
sigwait([signum])
pthread_sigmask(SIG_UNBLOCK, [signum])
print("done")
process.wait()
--------------------------
Same question than signalfd(): how can we block a signal in all threads (including C threads, e.g. _tkinter event looop thread)? Use sigprocmask()?
sigwait() removes the signal from the list of pending signals, so the signal handler will not be called.
> Note that exposing sigtimedwait is probably useful anyway,
> and I'd like to work on a patch.
See also issue #8407 for sigtimedwait() and signalfd() in Python.
---
sigprocmask(), sigwait() and signals in general seem to behave differently on each OS, so anyway, we cannot write a single portable implementation to solve this issue. If we cannot write a reliable non-polling implementation for an OS, you should use the polling implementation instead (which *is* reliable).
----------
_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue12187>
_______________________________________
More information about the Python-bugs-list
mailing list