[Python-Dev] Signals, threads, blocking C functions

Adam Olsen rhamph at gmail.com
Tue Sep 12 22:53:49 CEST 2006


On 9/12/06, Gustavo Carneiro <gjcarneiro at gmail.com> wrote:
> On 9/12/06, Adam Olsen <rhamph at gmail.com> wrote:
> > My previous mention of using a *single* flag may survive corruption
> > simply because we can tolerate false positives.  Signal handlers would
> > write 0xFFFFFFFF, the poll loop would check if *any* bit is set.  If
> > so, write 0x0, read off the fd, then loop around and check it again.
> > If the start of the read() acts as a write-barrier it SHOULD guarantee
> > we don't miss any positive writes.
>
>   Why write 0xFFFFFFFF?  Why can't the variable be of a "volatile
> char" type?  Assuming sizeof(char) == 1, please don't tell me
> architecture XPTO will write the value 4 bits at a time! :P

Nope.  It'll write 32 bits, then break that up into 8 bits :)
Although, at the moment I can't fathom what harm that would cause...

For the record, all volatile does is prevent compiler reordering
across sequence points.

Interestingly, it seems "volatile sig_atomic_t" is the correct way to
declare a variable for (single-threaded) signal handling.  Odd that
volatile didn't show up in any of the previous documentation I read..


>   I see your point of using a flag to avoid the read() syscall most of
> the time.  Slightly more complex, but possibly worth it.
>
>   I was going to describe a possible race condition, then wrote the
> code below to help explain it, modified it slightly, and now I think
> the race is gone.  In any case, the code might be helpful to check if
> we are in sync.  Let me know if you spot any  race condition I missed.
>
>
> static volatile char signal_flag;
> static int signal_pipe_r, signal_pipe_w;
>
> PyErr_CheckSignals()
> {
>   if (signal_flag) {
>      char signum;
>      signal_flag = 0;
>      while (read(signal_pipe_r, &signum, 1) == 1)
>          process_signal(signum);
>   }
> }

I'd prefer this to be a "while (signal_flag)" instead, although it
should technically work either way.


> static void
> signal_handler(int signum)
> {
>    char signum_c = signum;
>    signal_flag = 1;
>    write(signal_pipe_w, &signum_c, 1);
> }

This is wrong.  PyErr_CheckSignals could check and clear signal_flag
before you reach the write() call.  "signal_flag = 1" should come
after.

-- 
Adam Olsen, aka Rhamphoryncus


More information about the Python-Dev mailing list