Bug 4696 - ping hangs on certain unresolvable hosts
Summary: ping hangs on certain unresolvable hosts
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 2.2-STABLE
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 1997-10-05 19:30 UTC by marcs
Modified: 2004-02-29 21:06 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description marcs 1997-10-05 19:30:00 UTC
$ ping cban
PING cban.cban.com (204.209.160.1): 56 data bytes
^C^C^C^C^C^C^C
[... and it doesn't exit...]

The namesever for the above host is not reachable right now, so
trying to do the reverse lookup hangs for a long period of
time.  The problem is that ^C won't exit.  This is because 
the SIGINT signal handler just sets a flag telling ping to 
exit.  That doesn't do anything because ping in a select() in 
res_send which is retried if it gets an EINTR.

0x80873b1 in select ()
(gdb) up
#1  0x806b5a0 in res_send ()
(gdb) up
#2  0x8067eaa in res_query ()
(gdb) up
#3  0x8063786 in _gethostbydnsaddr ()
(gdb) up
#4  0x8062156 in gethostbyaddr ()
(gdb) up
#5  0x361e in pr_addr (ina={s_addr = 1772147148}) at ping.c:1168
1168            if ((options & F_NUMERIC) ||
(gdb)


This problem was introduced in revision 1.22 of ping.c.

Fix: 

Perhaps do a setjmp somewhere then have the signal handler do a 
longjmp out and have it check the flag then.

Lowering the _res timeouts for the resolver would help a little,
but isn't really a good solution because it would still hang for
a bit and because it would result in false negatives for reverses
for a small number of hosts.
How-To-Repeat: 
Find a host where all the nameservers are unreachable for the reverse
lookup.  ping it.
Comment 1 Masafumi Max NAKANE freebsd_committer freebsd_triage 1997-10-06 23:44:23 UTC
Responsible Changed
From-To: gnats-admin->freebsd-bugs

Misfiled PR. 
Comment 2 Kris Kennaway freebsd_committer freebsd_triage 2000-09-04 23:21:48 UTC
State Changed
From-To: open->closed

Fixed by sef in r1.24 of ping.c on 1997/07/13
Comment 3 Bruce Evans 2000-09-05 15:09:49 UTC
On Mon, 4 Sep 2000 kris@FreeBSD.ORG wrote:

> Synopsis: ping hangs on certain unresolvable hosts
> 
> State-Changed-From-To: open->closed
> State-Changed-By: kris
> State-Changed-When: Mon Sep 4 15:21:48 PDT 2000
> State-Changed-Why: 
> Fixed by sef in r1.24 of ping.c on 1997/07/13

No, this was only fixed for some values of "certain", and not the ones
described in the PR.

Rev.1.24 of ping.c mainly makes all syscalls return EINTR when they are
interrupted by a SIGINT or SIGALRM.  This fixes hangs in sendto() and/or
recvmsg(), but has no effect on the hangs described in the PR since
those involve select() and select() always returns EINTR when it is
interrupted.  As described in the PR, res_send() retries almost endlessly
after select() returns EINTR.

I think this is a bug in res_send().  It can't be aborted by non-broken
signal handlers except by ones that do little more than call _exit(2).
ping used to have broken signal handlers that did lots of unsafe cleanups
before exiting unsafely by calling exit(3).

PR 20613 is about essentially the same bug for "fetch -T n".  The timeout
doesn't work when the SIGALRM occurs in res_send(), since res_send() just
retries after select() returns EINTR.

Bruce
Comment 4 Bruce Evans freebsd_committer freebsd_triage 2000-09-06 15:12:22 UTC
State Changed
From-To: closed->open

Closed in error.
Comment 5 iedowse freebsd_committer freebsd_triage 2004-02-08 22:04:13 UTC
State Changed
From-To: open->patched


A partial workaround has been committed in revision 1.102 of ping.c. 
This just allows you to exit ping by hitting ^C a second time in 
the case where it is waiting for gethostbyaddr() to complete.
Comment 6 iedowse freebsd_committer freebsd_triage 2004-02-29 21:05:48 UTC
State Changed
From-To: patched->closed


Patch MFC'd to -STABLE now.