STINNER Victor <victor.stin...@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 <rep...@bugs.python.org>
<http://bugs.python.org/issue12187>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to