Bug 20613

Summary: fetch -T n is not timeout correctly when target server is down
Product: Base System Reporter: Masachika ISHIZUKA <ishizuka>
Component: binAssignee: Dag-Erling Smørgrav <des>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.1-RELEASE   
Hardware: Any   
OS: Any   

Description Masachika ISHIZUKA 2000-08-15 12:50:00 UTC
	% fetch -T 5 http://www.hoge.com/index.html

	When server 'www.hoge.com' is down or can't lookup address from
	DNS server, fetch command is not timeout with 5 seconds.
	Older version of fetch (with 4.0R or 3.4R) is timeout with 5 seconds.
Comment 1 Bruce Evans 2000-08-15 17:48:58 UTC
On Tue, 15 Aug 2000 ishizuka@ish.org wrote:

> >Description:
> 
> 	% fetch -T 5 http://www.hoge.com/index.html
> 
> 	When server 'www.hoge.com' is down or can't lookup address from
> 	DNS server, fetch command is not timeout with 5 seconds.
> 	Older version of fetch (with 4.0R or 3.4R) is timeout with 5 seconds.

This reminded me of an old problem with ping(8).  ^C doesn't work for
killing ping when DNS lookup hangs, provided you wait a second or two
for execution to reach res_send().  This is because res_send() retries
after EINTR, so it doesn't work with signal handlers that just set a
flag.  ping's SIGINT handler was fixed a few years ago to just set a
flag (previously it called stdio functions).

The problem in fetch(1) seems to be the same.  fetch's SIGINT and
SIGALRM handlers just set a flag, so neither -T nor ^C can be used to
kill fetch when DNS lookup hangs.

ping's SIGALRM handler also just sets a flag, but this works right
because ping only uses alarms to control syscalls and EINTR works
right for syscalls.

Bruce
Comment 2 Sheldon Hearn freebsd_committer freebsd_triage 2000-08-16 09:03:48 UTC
Responsible Changed
From-To: freebsd-bugs->des

Over to the maintainer.
Comment 3 ume 2000-08-16 18:52:50 UTC
On Tue, 15 Aug 2000 ishizuka@ish.org wrote:

> >Description:
> 
>  % fetch -T 5 http://www.hoge.com/index.html
> 
>  When server 'www.hoge.com' is down or can't lookup address from
>  DNS server, fetch command is not timeout with 5 seconds.
>  Older version of fetch (with 4.0R or 3.4R) is timeout with 5 seconds.

I cannot realize this problem with accessing
http://www.hoge.com/index.html.  However, I heared from you that
fetching to the server where is actually not exist something like
"fetch -T 1 http://10.1.1.1/aaa.txt" causes this problem.
Is this patch fix your problem?

Index: lib/libfetch/common.c
diff -u lib/libfetch/common.c.orig lib/libfetch/common.c
--- lib/libfetch/common.c.orig	Tue Jul 18 07:01:26 2000
+++ lib/libfetch/common.c	Thu Aug 17 02:36:42 2000
@@ -201,7 +201,12 @@
 	if ((sd = socket(res->ai_family, res->ai_socktype,
 			 res->ai_protocol)) == -1)
 	    continue;
-	if (connect(sd, res->ai_addr, res->ai_addrlen) != -1)
+	if (fetchTimeout)
+	    alarm(fetchTimeout);
+	err = connect(sd, res->ai_addr, res->ai_addrlen);
+	if (fetchTimeout)
+	    alarm(0);
+	if (err != -1)
 	    break;
 	close(sd);
 	sd = -1;

--
Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
ume@mahoroba.org  ume@bisd.hitachi.co.jp  ume@FreeBSD.org
http://www.imasy.org/~ume/
Comment 4 Masachika ISHIZUKA 2000-08-17 01:39:16 UTC
>>>Description:
>> 
>>  % fetch -T 5 http://www.hoge.com/index.html
>> 
>>  When server 'www.hoge.com' is down or can't lookup address from
>>  DNS server, fetch command is not timeout with 5 seconds.
>>  Older version of fetch (with 4.0R or 3.4R) is timeout with 5 seconds.
> 
> I cannot realize this problem with accessing
> http://www.hoge.com/index.html.  However, I heared from you that
> fetching to the server where is actually not exist something like
> "fetch -T 1 http://10.1.1.1/aaa.txt" causes this problem.
> Is this patch fix your problem?
> 
> Index: lib/libfetch/common.c
> diff -u lib/libfetch/common.c.orig lib/libfetch/common.c
> --- lib/libfetch/common.c.orig	Tue Jul 18 07:01:26 2000
> +++ lib/libfetch/common.c	Thu Aug 17 02:36:42 2000
> @@ -201,7 +201,12 @@
>  	if ((sd = socket(res->ai_family, res->ai_socktype,
>  			 res->ai_protocol)) == -1)
>  	    continue;
> -	if (connect(sd, res->ai_addr, res->ai_addrlen) != -1)
> +	if (fetchTimeout)
> +	    alarm(fetchTimeout);
> +	err = connect(sd, res->ai_addr, res->ai_addrlen);
> +	if (fetchTimeout)
> +	    alarm(0);
> +	if (err != -1)
>  	    break;
>  	close(sd);
>  	sd = -1;

  Hi, this is ishizuka.
  Thank you very much.  This patch fixed my problem.
And, sorry to say that I wrote 'www.hoge.com' to mean
'some.nonexist.domain.or.server' but this domain and this
server really exists.

-- 
ishizuka@ish.org
Comment 5 des 2000-08-30 10:10:22 UTC
I'm aware of the problem, but not quite sure how to handle it. The
timeout should be enforced by libfetch, not by fetch(1), but I can't
see any easy way of doing it.

DES
-- 
Dag-Erling Smorgrav - des@flood.ping.uio.no
Comment 6 Dag-Erling Smørgrav freebsd_committer freebsd_triage 2002-10-29 09:31:08 UTC
State Changed
From-To: open->feedback

Fixed in -CURRENT, awaiting MFC.
Comment 7 Dag-Erling Smørgrav freebsd_committer freebsd_triage 2002-11-27 15:45:43 UTC
State Changed
From-To: feedback->closed

Fixed, thanks.