A Python interface to signalfd() using FFI

I just recently learned about the signalfd(2) system call, which was
introduced to the Linux kernel back in 2007:

signalfd() creates a file descriptor that can be used to accept
signals targeted at the caller. This provides an alternative to
the use of a signal handler or sigwaitinfo(2), and has the
advantage that the file descriptor may be monitored by select(2),
poll(2), and epoll(7).

The traditional asynchronous delivery mechanism can be tricky to get
right, whereas this provides a convenient fd interface that integrates
nicely with your existing event-based code.

I was interested in using signalfd() in some Python code, but Python
does not expose this system call through any of the standard
libraries. There are a variety of ways one could add support,
including:

What all this means is that you need to translate sigset_t into
standard C types. You could go digging through include files in
/usr/include, but an easier method is to create a small C source
file like this:

#include <sys/signalfd.h>

And then run it through the preprocessor:

$ gcc -E sourcefile.c

Inspecting the output of this command reveals that sigset_t is a
typedef for __sigset_t, and that __sigset_t looks like this:

In case it’s not obvious from the above example, when I typed
CONTROL-C on my keyboard, sending a SIGINT to the Python shell, it
caused the p.poll() method to exit, reporting activity on fd 3
(which is the fd we were given by signalfd()). We call
sigprocmask(2) to prevent the normal asynchronous delivery of
signals, which would otherwise result in Python handling the SIGINT
and generating a KeyboardInterrupt exception.

You can find this all packaged up nicely with a slightly more pythonic
interface in my python-signalfd repository on GitHub.