Bug 162064 - [patch] Loop in fetch(1) when sending SIGINFO after the server stopped sending data
Summary: [patch] Loop in fetch(1) when sending SIGINFO after the server stopped sendin...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-10-27 17:20 UTC by Fabian Keil
Modified: 2012-03-12 19:29 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 Fabian Keil 2011-10-27 17:20:07 UTC
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@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@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@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.
Comment 1 Mark Johnston 2012-03-12 02:52:33 UTC
This is very similar to/exactly the problem I fixed in libfetch a
little while ago. Indeed, I can't reproduce it on my laptop running
CURRENT. See r230307 and bin/153240.

-Mark
Comment 2 Fabian Keil 2012-03-12 17:27:08 UTC
Mark Johnston <markjdb@gmail.com> wrote:

> This is very similar to/exactly the problem I fixed in libfetch a
> little while ago. Indeed, I can't reproduce it on my laptop running
> CURRENT. See r230307 and bin/153240.


I noticed r230307 and while I assumed that it might fix it,
I didn't get around to testing it yet.

Thanks for the reminder (and the fix of course).

I can confirm that the problem is no longer reproducible.
As far a I'm concerned the PR can be closed.

Fabian
Comment 3 Mark Linimon freebsd_committer freebsd_triage 2012-03-12 19:29:20 UTC
State Changed
From-To: open->closed

Apparently this has already been fixed.