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

Gustavo Carneiro gjcarneiro at gmail.com
Tue Sep 12 19:15:48 CEST 2006


On 9/12/06, Adam Olsen <rhamph at gmail.com> wrote:
> On 9/12/06, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> > Adam Olsen wrote:
> >
> > > That brings you back to how you access the flags variable.
> >
> > The existing signal handler sets a flag, doesn't it?
> > So it couldn't be any more broken than the current
> > implementation.
> >
> > If we get too paranoid about this, we'll just end
> > up deciding that signals can't be used for anything,
> > at all, ever. That doesn't seem very helpful,
> > although techically I suppose it would solve
> > the problem. :-)
> >
> > My own conclusion from all this is that if you
> > can't rely on writing to a variable in one part
> > of your program and reading it back in another,
> > then computer architectures have become far
> > too clever for their own good. :-(
>
> They've been that way for a long, long time.  The irony is that x86 is
> immensely stupid in this regard, and as a result most programmers
> remain unaware of it.
>
> Other architectures have much more interesting read/write and cache
> reordering semantics, and the code is certainly broken there.  C
> leaves it undefined with good reason.
>
> 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

  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);
  }
}

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


More information about the Python-Dev mailing list