|
Home > Archive > Unix Programming > January 2004 > unix network programming vol I ed2 race condition, confirm plz
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
unix network programming vol I ed2 race condition, confirm plz
|
|
|
| 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
if (sigsetjmp(jmpbuf, 1) != 0) {
if (rtt_timeout(&rttinfo) < 0) {
err_msg("dg_send_recv: no response from server,
giving up");
rttinit = 0; /* reinit in case we're called
again */
errno = ETIMEDOUT;
return(-1);
}
#ifdef RTT_DEBUG
err_msg("dg_send_recv: timeout, retransmitting");
#endif
goto sendagain;
}
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?
thanks!
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.
| |
| Michael Fuhr 2004-01-23, 5: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/
| |
|
| cool thanks for the reply michael. im waiting on vol 3 for my
birthday(22nd) so i'll confirm this when i get that.
Michael Fuhr wrote:quote:
> inf <britney_spears@hotpop.com> writes:
>
>
>
>
> My copy of the book doesn't have the above #ifdef, but otherwise the
> code looks the same.
>
>
>
>
> [snip]
>
>
>
>
> 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.
>
>
>
>
> 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 2004-01-23, 5:33 pm |
| inf <britney_spears@hotpop.com> writes:
quote:
> Michael Fuhr wrote:
>
> cool thanks for the reply michael. im waiting on vol 3 for my
> birthday(22nd) so i'll confirm this when i get that.
The race condition still appears in the 3rd edition, on p. 603 as
I recall from a quick check in a book store.
--
Michael Fuhr
http://www.fuhr.org/~mfuhr/
|
|
|
|
|