Skip site navigation (1)Skip section navigation (2)
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>