signalfd

This article covers signalfd, a system call only available on Linux. If anyone knows of an equivalent for OSX or BSDs,* please let me know. It’d be great to create a compatibility layer.

Writing asynchronous IO code is fun; handling signals is not. signalfd allows you to move your signal handling code into your main event loop instead of hooking up global handlers and using the featureless set_wakeup_fd function to break the main loop.

Luckily Jean-Paul Calderone had already created a great Python wrapper for the signalfd and sigprocmask system calls. Unfortunately it doesn’t include a way to parse the siginfo_t structure which contains all the useful information about the signal you’re handling.

I’ve added a helper to do just that in a branch:

https://code.launchpad.net/~schmichael/python-signalfd/helpers

A sample program would look like:

 
import os
import select
import signal
 
import signalfd
 
 
def sigfdtest():
    # Catch them all!
    sigs = []
    for attr in dir(signal):
        if attr.startswith('SIG') and not attr.startswith('SIG_'):
            sigs.append(getattr(signal, attr))
 
    sfd = signalfd.create_signalfd(sigs)
    print 'Capturing: %r' % sorted(sigs)
 
    while 1:
        print 'selecting - pid: %d' % os.getpid()
        r = select.select([sfd], [], [])[0]
        for s in r:
            assert s is sfd, 'Python nicely re-uses the fd instance'
            sig = signalfd.read_signalfd(sfd)
            print sig
 
 
if __name__ == '__main__':
    sigfdtest()

When run you can throw some signals at it:

Capturing: [6, 14, 7, 17, 17, 18, 8, 1, 4, 2, 29, 6, 9, 13, 29, 27, 30, 3, 64, 34, 11, 19, 31, 15, 5, 20, 21, 22, 23, 10, 12, 26, 28, 24, 25]
selecting - pid: 6523
^CSIGINT
selecting - pid: 6523
^CSIGINT
selecting - pid: 6523
SIGHUP
selecting - pid: 6523
Killed

Of course you’ll need to use an uninterpretable signal like KILL to exit.

Jean-Paul attempted to get signalfd included in Python 2.7’s signal module, and it was slated for inclusion in 3.2. However, given that 3.2 was just released without it, I’m guessing the attempt to get this functionality into Python’s stdlib has been forgotten.

Up next: eventfd perhaps?

This entry was posted in GNU/Linux, Open Source, Python, Technology. Bookmark the permalink.
  • https://launchpad.net/pyeventfs Andrew E. Falcon

    If you’re interested in using linux’s other eventfs features (eventfd, timerfd), I have source available for python.

    https://code.launchpad.net/~aefalcon/pyeventfs/trunk

  • Tom Dial

    Doesn’t kqueue / kevent on BSD support signal handling?

  • http://blog.schmichael.com/ Michael Schurter

    As I said in the opening paragraph: “This article covers signalfd, a system call only available on Linux. If anyone knows of an equivalent for OSX or BSDs,* please let me know.”

    I’m only personally interested in Linux, but please let me know if you find out anything about OSX or BSDs.