[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