|
From: Jeremy F. <je...@go...> - 2003-08-18 18:01:05
|
On Mon, 2003-08-18 at 10:19, Steve G wrote: > >In my experience, however, programs which use such a > >simple scheme are prone to signal race deadlocks. > > Not really...it just depends on what your job is. I > re-wrote the signal handlers in proftpd about a year and > half ago using flags. The signal handlers set a flag when > something of interest occurs. The handler is call from the > main loop which periodically polls the flag. The handlers > reset the flag first, and then do the work. They completely > process everything pending. The worst case is that the same > signal is delivered while processing that flag. This causes > a call to the signal handler for which no work is waiting. Yes, this is the case where sigwait/sigtimedwait allows you to consume pending signals without async delivery - which makes the whole issue of calling handlers moot. > There's no way to protect data structures using process > synchronization techniques from a signal handler. Either > you have to do you homework up front in the design making > sure nothing steps on each other, or using signals as flags > and not as hardware interrupt handlers. Well, that's not really true. You can use sigprocmask to defer delivery of a signal for as long as you need to, so you can use it to protect your critical sections. > In case you missed the way that stunnel works, what it does > is create a signal pipe. Whenever a signal comes in, it > writes to the pipe. The pipe is added to the fd_set that > select watches. Whenever a signal occurs, the pipe becomes > readable and it goes off to handle that event. Write() is a > legal function call from a signal handler. What's written > to the pipe is an integer which is sigatomic in size. Right, that's what I do in the autofs4 autmount as well. It means that you're not relying on the signal to interrupt the syscall directly; you're using the normal select mechanisms. There's a theoretical risk of deadlock if the pipe fills up, but that just means you need to select/poll often enough. > Xinetd does the same thing except it uses a different > integer for each signal. The only issue you have to watch > when using the pipe technique for serialization is to call > fcntl(fd, F_SETFD, CLOEXEC); so you don't leak the pipe > descriptor. If you're forking child processes (no exec) you also have to be careful not to end up sharing your message pipe. (I'd really like CLOFORK.) > > >I think the most common case of manipulating data > >structures from a signal handler is in programs which > >keep track of their child processes: > > These are all fundamentally broken. See > http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2002-1563 > for a good reason why stunnel moved to the current > technique. I disagree, because you can use sigprocmask to get it right. On the other hand, it is error-prone (like any multi-threaded programming), so it would be nice to have a tool to test for correctness. Hence this thread on this list. J |