[Python-Dev] Signals+Threads (PyGTK waking up 10x/sec).

Adam Olsen rhamph at gmail.com
Sun Dec 9 00:57:25 CET 2007

On Dec 8, 2007 4:28 PM, Guido van Rossum <guido at python.org> wrote:
> On Dec 8, 2007 2:36 PM, Adam Olsen <rhamph at gmail.com> wrote:
> > On Dec 8, 2007 2:56 PM,  <glyph at divmod.com> wrote:
> > > On 05:20 pm, guido at python.org wrote:
> > > >The best solution I can think of is to add a new API that takes a
> > > >signal and a file descriptor and registers a C-level handler for that
> > > >signal which writes a byte to the file descriptor. You can then create
> > > >a pipe, connect the signal handler to the write end, and add the read
> > > >end to your list of file descriptors passed to select() or poll(). The
> > > >handler must be written in C in order to avoid the race condition
> > > >referred to by Glyph (signals arriving after the signal check in the
> > > >VM main loop but before the select()/poll() system call is entered
> > > >will not be noticed until the select()/poll() call completes).
> > >
> > > This paragraph jogged my memory.  I remember this exact solution being
> > > discussed now, a year ago when I was last talking about these issues.
> > >
> > > There's another benefit to implementing a write-a-byte C signal handler.
> > > Without this feature, it wouldn't make sense to have passed the
> > > SA_RESTART flag to sigaction, because and GUIs written in Python could
> > > have spent an indefinite amount of time waiting to deliver their signal
> > > to Python code.  So, if you had to handle SIGCHLD in Python, for
> > > example, calls like file().write() would suddenly start raising a new
> > > exception (EINTR).  With it, you could avoid a whole class of subtle
> > > error-handling code in Twisted programs.
> >
> > SA_RESTART still isn't useful.  The low-level poll call (not write!)
> > must stop and call back into python.  If that doesn't indicate an
> > error you can safely restart your poll call though, and follow it with
> > a (probably non-blocking) write.
> Can't say I understand all of this, but it does reiterate that there
> are more problems with signals than just the issue that Gustavo is
> trying to squash. The possibility of having *any* I/O interrupted is
> indeed a big worry. Though perhaps this could be alleviated by rigging
> things so that signals get delivered (at the C level) to the main
> thread and the rest of the code runs in a non-main thread?

That's the approach my threading patch will take, although reversed
(signals are handled by a background thread, leaving the main thread
as the *main* thread.)

I share your concern about interrupting whatever random syscalls (not
even limited to I/O!) that a library happens to use.

> > Note that the only reason to use C for a low-level handler here is
> > give access to sigatomic_t and avoid needing locks.  If you ran the
> > signal handler in a background thread (using sigwait to trigger them)
> > you could use a python handler.
> I haven't seen Gustavo's patch yet, but *my* reason for using a C
> handler was different -- it was because writing a byte to a pipe in
> Python would do nothing to fix Gustavo's issue.
> Looking at the man page for sigwait()  it could be an alternative
> solution, but I'm not sure how it would actually allow PyGTK to catch
> KeyboardInterrupt.

My mail at [1] was referring to this.  Option 1 involved writing to a
pipe that gets polled while option 2 requires we generate a new signal
targeting the specific thread we want to interrupt.

I'd like to propose an interim solution though: pygtk could install
their own SIGINT handler during the gtk mainloop (or all gtk code?),
have it write to a pipe monitored by gtk, and have gtk raise
KeyboardInterrupt if it gets used.  This won't allow custom SIGINT
handlers or any other signal handlers to run promptly, but it should
be good enough for OLPC's use case.

[1] http://mail.python.org/pipermail/python-dev/2007-December/075607.html

Adam Olsen, aka Rhamphoryncus

More information about the Python-Dev mailing list