Date: Mon, 9 Feb 2004 02:39:02 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: "Jukka A. Ukkonen" <jau@iki.fi> Cc: freebsd-gnats-submit@freebsd.org Subject: Re: kern/62524: SIGALRM is not delivered when res_send() hangs waiting in kevent() Message-ID: <20040209021755.P44973@gamplex.bde.org> In-Reply-To: <200402081121.i18BLwEl037903@www.freebsd.org> References: <200402081121.i18BLwEl037903@www.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040209021755.P44973>