A gotcha with Python's new signal.siginterrupt()

August 22, 2009

Python 2.6 added a siginterrupt() function to the signal module, so that you can deal with the EINTR problem. Unfortunately it doesn't necessarily do what you want, because of CPython signal handler semantics.

(Ob-attribution: signal.siginterrupt() was brought to my attention by a commentator on the EINTR entry.)

What you probably want when you combine siginterrupt() and a signal handler, and what a lot of people probably think that they are getting, is that when your program is sitting in a system call and gets a signal, your signal handler function gets called and does its thing while the system call just keeps going, none the wiser. (This is what happens in C, more or less.)

What you get instead is that processing the signal is deferred until the system call completes. Your program is sitting in a system call, gets a signal, and (as far as your Python code is concerned) absolutely nothing happens until the system call completes, whenever that is. Only then does your signal handler function wake up and do its thing.

This happens because CPython only runs Python signal handler functions when control returns to the bytecode interpreter. System calls failing with EINTR is the brute force mechanism that normally causes this to happen relatively soon after your program gets a signal; the program gets a signal, the system call fails with EINTR, the C code making the system call notices this and raises an exception, which returns control to the bytecode interpreter. When system calls don't get EINTR any more, the whole chain of events stops (well, never gets started) and there you are, waiting for the system call to finish normally.

One might hope that Python's siginterrupt() does something clever to get around this, but it doesn't; it is strictly a wrapper for the C library siginterrupt(3) function. (It probably has to be, since I think that doing otherwise would require C module API changes.)

There are probably situations and signal handlers where this is acceptable, or at least the least worst choice, but I do think that it makes siginterrupt() a lot less useful than it first appears.

(I also think that this should be explicitly mentioned in the siginterrupt() description, although you can work it out from the current documentation if you put all of the pieces together.)

Written on 22 August 2009.
« The danger of powerful generality, illustrated
You should not use HTTP request parameters as filenames »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sat Aug 22 00:29:03 2009
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.