bin/162064: Loop in fetch when sending SIGINFO after the server
stopped sending data
Fabian Keil
fk at fabiankeil.de
Thu Oct 27 16:20:08 UTC 2011
>Number: 162064
>Category: bin
>Synopsis: Loop in fetch when sending SIGINFO after the server stopped sending data
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu Oct 27 16:20:07 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator: Fabian Keil
>Release: HEAD
>Organization:
>Environment:
FreeBSD r500.local 10.0-CURRENT FreeBSD 10.0-CURRENT #370 r+e5cde8a: Tue Oct 25 21:12:37 CEST 2011 fk at r500.local:/usr/obj/usr/src/sys/ZOEY amd64
>Description:
If fetch receives SIGINFO after the server stopped sending
data it goes into a loop and starts eating 100% cpu even
continuing after the connection to the server has been
closed.
It's my impression that fetch.c relies on fread() to modify
errno in a way it doesn't. The following patch prevents the
cpu-eating loop, but fetch still fails to properly save the
received data:
commit 2131ebe654b5d9b48a715ea1955941b9d3e89f4d
Author: Fabian Keil <fk at fabiankeil.de>
Date: Sat Oct 15 22:12:54 2011 +0200
Manually set errno to 0 before calling fread() in fetch().
The fact that this makes a difference seems to suggest
that fread() doesn't behave like fetch expects it to.
diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c
index 9862276..18c6d5a 100644
--- a/usr.bin/fetch/fetch.c
+++ b/usr.bin/fetch/fetch.c
@@ -636,6 +636,7 @@ fetch(char *URL, const char *path)
stat_end(&xs);
siginfo = 0;
}
+ errno = 0; /* XXX: Why does this have an effect? */
if ((size = fread(buf, 1, size, f)) == 0) {
if (ferror(f) && errno == EINTR && !sigint)
clearerr(f);
>How-To-Repeat:
Run a "webserver" like this one:
(printf "HTTP/1.1 200 Okay\r\nConnection: close\r\nContent-Length: 10\r\n\r\n0123456789"; sleep 5) | nc -l 81
Use fetch to request a resource, send SIGINFO before the sleep
time is up and watch it eating cpu time without doing anything
useful:
fk at r500 ~ $fetch http://127.0.0.1:81/
fetch.out 0% of 10 B 0 Bps
load: 0.80 cmd: fetch 3698 [select] 0.70r 0.00u 0.00s 0% 2464k
fetch.out 0% of 10 B 0 Bps
fetch.out 0% of 10 B 0 Bps
load: 0.83 cmd: fetch 3698 [runnable] 12.32r 0.64u 10.96s 70% 2504k
fetch.out 0% of 10 B 0 Bps
fetch.out 0% of 10 B 0 Bps
load: 0.87 cmd: fetch 3698 [running] 24.50r 1.22u 22.54s 96% 2504k
fetch.out 0% of 10 B 0 Bps
fetch.out 0% of 10 B 0 Bps
load: 0.91 cmd: fetch 3698 [running] 52.70r 2.84u 49.10s 100% 2504k
fetch.out 0% of 10 B 0 Bps
fetch.out 0% of 10 B 0 Bps
load: 0.92 cmd: fetch 3698 [running] 59.60r 3.26u 55.55s 100% 2504k
fetch.out 0% of 10 B 0 Bps
fetch.out 0% of 10 B 0 Bps^C
fetch: transfer interrupted
With the errno patch one gets:
fk at r500 /tank/scratch $fetch http://127.0.0.1:81/
fetch.out 0% of 10 B 0 Bps
load: 0.74 cmd: fetch 3812 [select] 0.69r 0.00u 0.00s 0% 2464k
fetch.out 0% of 10 B 0 Bps
fetch.out 0% of 10 B 0 Bps
fetch: http://127.0.0.1:81/: No error: 0
and no output file even though all the data has been delivered.
If SIGINFO isn't sent, the resource is properly received.
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list