Author neologix
Recipients benjamin.peterson, exarkun, giampaolo.rodola, gregory.p.smith, jcea, loewis, marcin.bachry, neologix, pitrou, python-dev, schmichael, skrah, spiv, tseaver, vstinner
Date 2011-06-10.09:30:10
SpamBayes Score 1.5152e-11
Marked as misclassified No
Message-id <BANLkTi=Rk4+b=xtjuUjySEYt5vwf+DQFAQ@mail.gmail.com>
In-reply-to <1307663663.89.0.41178639954.issue8407@psf.upfronthosting.co.za>
Content
>> I just noticed something "funny": signal_sigwait doesn't release
>> the GIL, which means that it's pretty much useless :-)
>
> sigwait() is not useless: the signal is not necessary send by another thread. The signal can be send by alarm(), from a child process, by an user, by the kernel.
>

If it doesn't release the GIL, it is useless.
The common usage pattern for sigwait() is to create a dedicated thread
for signals management. If this thread calls sigwait without releasing
the GIL, the whole process is suspended, which is definitely not what
you want.

>> Also, test_sigwait doesn't block the signal before calling sigwait:
>> it happens to work because there's only one thread, but it's
>> undefined behaviour.
>
> test_sigwait() test pass on all 3.x buildbots (some don't have sigwait(), the test is skipped). Sometimes, test_sigwait() is executed with 2 threads, the main thread and Tkinter event loop thread, and the signal is not blocked in any thread.
>

It's mere luck:

    def test_sigwait(self):
        old_handler = signal.signal(signal.SIGALRM, self.handler)
        self.addCleanup(signal.signal, signal.SIGALRM, old_handler)

        signal.alarm(1)
        self.assertEqual(signal.sigwait([signal.SIGALRM]), signal.SIGALRM)

Comment out the first two lines that change the signal handler, and
the test will be killed by SIGALRM's default handler ("Alarm clock").
I tested on Linux, and if a the signal isn't blocked before calling sigwait:
- if a custom signal handler is installed, then it is not called
- if the default signal handler is in place, then it's called (and
with SIGALRM the process gets killed)
This is a typical example of what POSIX calls "undefined behavior".
If pthread_sigmask is called before sigwait, then it works as expected.

If we really wanted to test this properly, the way to go would be to
fork() a child process (that way we're sure there's only one thread),
have it block and sigwait() SIGUSR1 without touching the handler, send
it SIGUSR1, and check its return code.
Patch attached.
Files
File name Uploaded
test_sigwait.diff neologix, 2011-06-10.09:30:09
History
Date User Action Args
2011-06-10 09:30:11neologixsetrecipients: + neologix, loewis, gregory.p.smith, jcea, spiv, exarkun, tseaver, pitrou, vstinner, giampaolo.rodola, benjamin.peterson, marcin.bachry, schmichael, skrah, python-dev
2011-06-10 09:30:10neologixlinkissue8407 messages
2011-06-10 09:30:10neologixcreate