开发者

siginterrupt() only works for the first signal? (Python)

For some reason, siginterrupt() only seems to set the behaviour for the first signal received.

In this example program, the first SIGQUIT appears to do nothing, but the second sigquit prints "SIGQUIT Handler" and s.accept() throws an Interrupted system call exception.

from signal import *
from socket import *
import sys

def sigquitHandler(signum, frame):
        print("SIGQUIT Handler")

s = socket()
s.bind(("0.0.0.0", int(sys.argv[1])))
s.listen(5)

signal(SIGQUIT, sigquitHandler)
siginterrupt(SIGQUIT, False)

client, addr = s.accept() # Or any syscall that blocks
client.close()
s.close()

What am i misunderst开发者_如何学Pythonanding here?


Edit: Here's something else that i can't figure out, in this program, a SIGQUIT interrupts the select(). Is that supposed to happen?

from signal import *
import select
import sys

def sigquitHandler(signum, frame):
    print("SIGQUIT Handler")

signal(SIGQUIT, sigquitHandler)
siginterrupt(SIGQUIT, False)

select.select([sys.stdin], [], [])


It's a bug of python. "siginterrupt with flag=False is reset when signal received", which has been fixed in later python2.6 release. (2.6.6+, 2.7+)

For the second one, siginterrupt doesn't affect select().

see http://lkml.org/lkml/2005/7/23/119


Which unix are you using? At the C level, there are different implementations and semantics for signal handling on BSD vs System 5 (SYSV).

My guess is that you are using SYSV, in which case the signal disposition is reset to SIG_DFL after the signal handler has returned (classical signal handling). On SYSV you need to call signal in the handler to reinstall that handler.

Python more or less provides BSD style signal handling. So, on a SYSV OS, Python must be managing reinstallation of the signal handler via signal. Now, according to the Python doco for siginterrupt:

Note that installing a signal handler with signal() will reset the restart behaviour to interruptible by implicitly calling siginterrupt() with a true flag value for the given signal.

And there you go - if Python is automatically reinstalling your signal handler (to provide BSD like semantics), it may well be doing so in a way that implicitly calls siginterrupt(1).

Of course, my guess could be wrong.

You might be able to fix this by defining sigquitHandler like this:

def sigquitHandler(signum, frame):
    print("SIGQUIT Handler")
    siginterrupt(SIGQUIT, False)

It depends on when and how Python is restoring the signal disposition.

EDIT

Adding siginterrupt(SIGQUIT, False) to the signal handler has no affect.

EDIT 2

After some more poking around in the Python2.6 source code it clear that this is not just a SYSV issue. It will affect BSD systems too.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜