kern/62524: SIGALRM is not delivered when res_send() hangs waiting in kevent()

Bruce Evans bde at zeta.org.au
Sun Feb 8 07:40:09 PST 2004


The following reply was made to PR kern/62524; it has been noted by GNATS.

From: Bruce Evans <bde at zeta.org.au>
To: "Jukka A. Ukkonen" <jau at iki.fi>
Cc: freebsd-gnats-submit at freebsd.org, freebsd-bugs at freebsd.org
Subject: Re: kern/62524: SIGALRM is not delivered when res_send() hangs
 waiting in kevent()
Date: Mon, 9 Feb 2004 02:39:02 +1100 (EST)

 On Sun, 8 Feb 2004, Jukka A. Ukkonen wrote:
 
 > >Description:
 > When an interval timer should trigger a SIGALRM delivery to
 > a process which tries to resolve an address to an FQDN and
 > there is no name service available for the corresponding
 > in-addr.arpa. domain the signal is not delivered.
 >
 > Instead the process simply hangs waiting in ...
 >
 > #0  0x280b3c00 in kevent () from /usr/lib/libc.so.4
 > #1  0x280c63f5 in res_send () from /usr/lib/libc.so.4
 > #2  0x280c9799 in res_query () from /usr/lib/libc.so.4
 > #3  0x280d5ccf in _gethostbydnsaddr () from /usr/lib/libc.so.4
 > #4  0x280d45f0 in gethostbyaddr () from /usr/lib/libc.so.4
 >
 > The process continues only when the resolver timeout expires.
 >
 > This is a disaster for any program which uses setitimer() and
 > SIGALRM to drive periodic tasks at regular intervals.
 >
 > It looks like kevent() is not properly interrupted by the signal.
 
 Are you sure that it doesn't get delivered?  There is an old bug
 in the resolver library that causes it to wait forever.  The signal
 gets delivered and (at least using select() instead of kevent())
 the resolver sees EINTR, but the resolver retries forever in some
 cases.  This breakes signal handling in ping(8).  The signal is
 delivered to ping but ping just sets a flag and waits for its main
 loop to be returned to to check the flag, but the resolver never
 returns.
 
 BTW, correct signal handlers that just set a flag often don't actually
 work.  E.g., top's signal handling was broken years ago by changing
 its hanflers to just set a flag.  The SIGINT handler is attached using
 signal(), so most syscalls don't return after a signal and top can't
 be killed by ^C when it is in such a syscall -- e.g., start top and
 type "s"; top then waits for input and if you type ^C then it keeps
 waiting for input and the ^C is not acted on until you type some input
 (or kill the program using an uncaught signal).  Signal handlers must
 be installed without SA_RESTART for the just-set-a-flag method to work,
 and then everything that does i/o, including stdio calls, needs to be
 SYSVified to expect EINTR.  Few programs or libraries get this right.
 
 Bruce


More information about the freebsd-bugs mailing list