01-23-04 10:32 PM
inf <britney_spears@hotpop.com> writes:
quote:
> hi, in chapter 20, the advanced UDP one, pg 548, i believe there is a
> race condition. the offending code looks like this:
>
> alarm(rtt_start(&rttinfo)); /* calc timeout value & start
> timer */
> #ifdef RTT_DEBUG
> rtt_debug(&rttinfo);
> #endif
My copy of the book doesn't have the above #ifdef, but otherwise the
code looks the same.
quote:
> if (sigsetjmp(jmpbuf, 1) != 0) {
[snip]
quote:
> and the signal handler code:
>
> static void
> sig_alrm(int signo)
> {
> siglongjmp(jmpbuf, 1);
> }
>
> the problem i see is a race between the call to alarm and the call to
> sigsetjmp. if the alarm goes off b4 the jump buffer is set the
> siglongjmp() in the handler will segfault since the jump buffer hasnt
> been initialized. have i overlooked something here or am i correct?
I think you're right. Interestingly, in _Advanced programming in
the UNIX Environment_, Stevens mentions this race condition and
handles it in Program 10.14 (pp 300-301). He says:
This program demonstrates another technique that should be used
whenever siglongjmp is being called from a signal handler. We set
the variable canjump nonzero only after we've called sigsetjmp.
This variable is also examined in the signal handler, and siglongjmp
is called only if the flag canjump is nonzero. This provides
protection against the signal handler being called at some earlier
or later time, when the jump buffer isn't initialized by sigsetjmp.
Regarding the behavior of calling longjmp/siglongjmp before
setjmp/sigsetjmp has been called, SUSv3/POSIX says this:
The longjmp() function shall restore the environment saved by the
most recent invocation of setjmp() in the same thread, with the
corresponding jmp_buf argument. If there is no such invocation, or
if the function containing the invocation of setjmp() has terminated
execution in the interim, or if the invocation of setjmp() was
within the scope of an identifier with variably modified type and
execution has left that scope in the interim, the behavior is
undefined.
I just ran a few tests: on Solaris 9 and Linux, the test program
died with SIGSEGV when siglongjmp() was called with an uninitialized
jump buffer. The same program run on FreeBSD 4.9 entered a
CPU-consuming mode that only SIGKILL would terminate.
quote:
> ps. i know its kinda anal to think that this would happen, but as ya
> know stevens has always said that is not an excuse and that is the
> perspective i have adopted.
More programmers should have this perspective. The conditions
necessary to cause a problem may seldom occur, but that's precisely
what makes such problems difficult to track down when they do happen.
A third edition of _UNIX Network Programming_, Volume 1, was recently
published; perhaps somebody with a copy could check whether the
race condition still appears. If it does, consider contacting the
new authors (Bill Fenner, Andrew M. Rudoff) and discussing it with
them.
--
Michael Fuhr
http://www.fuhr.org/~mfuhr/
[ Post a follow-up to this message ]
|