cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: Bug: curl 7.18.2/7.19.2 looses timeouts

From: <koettermarkus_at_gmx.de>
Date: Thu, 20 Nov 2008 17:04:42 +0100

Daniel Stenberg wrote:
> I reviewed the code right now and quite clearly these options have never
> worked properly for the multi interface. The speed check is only ever
> done in the lib/transfer.c:Curl_readwrite() function, and that is only
> called when one of the curl_multi_perform() or curl_multi_socket*()
> functions are called and the multi handle is in the CURLM_STATE_PERFORM
> state.
>
> This of course breaks for the cases when the state never enters the
> CURLM_STATE_PERFORM state (which seems to be what the
> listening-only-on-a-socket test case will show) or if not called enough
> times (with no or slow enough traffic) in that state.
>
> How to fix: the Curl_speedcheck() function needs to be called in just
> all multi states. It should also set the timeout timer properly so that
> when these options are used, the speed is checked at some clever
> interval even if no traffic at all is detected.
>

I had the same idea first, but figured out I might be wrong, as the
timer_cb gets called, and following the code path I figured when calling
curl_multi_socket_action( ... TIMEOUT ... )
Curl_readwrite() gets called.
Curl_readwrite() would call Curl_speecheck().
But I may be horrible wrong here.

Anyway, as I said, sometimes it works:

------------ working --------------
./evhiperfifo
Creating named pipe "hiper.fifo"
Now, pipe some URL's into > hiper.fifo
Adding easy 0xc9f5b8 to multi 0xc7c858 (http://localhost:9000)
multi_timer_cb 0
timer_cb w 0x7fff8973ca98 revents 0
* STATE: INIT => CONNECT handle 0xca8168; (connection #-5000)
* About to connect() to localhost port 9000 (#0)
* Trying 127.0.0.1... * connected
* Connected to localhost (127.0.0.1) port 9000 (#0)
* STATE: CONNECT => DO handle 0xca8168; (connection #0)
sock_cb e 0xc9f5b8 s 6 what 2 cbp 0x7fff8973ca60 sockp (nil)
socket callback: s=6 e=0xc9f5b8 what=OUT Adding data: OUT
setsock
> GET / HTTP/1.1
Host: localhost:9000
Accept: */*

* STATE: DO => DO_DONE handle 0xca8168; (connection #0)
sock_cb e 0xc9f5b8 s 6 what 1 cbp 0x7fff8973ca60 sockp 0xca9c40
socket callback: s=6 e=0xc9f5b8 what=IN Changing action from OUT to IN
setsock
* STATE: DO_DONE => WAITPERFORM handle 0xca8168; (connection #0)
* Conn 0 recv pipe 1 inuse 0 athead 1
* STATE: WAITPERFORM => PERFORM handle 0xca8168; (connection #0)
Progress: http://localhost:9000 (0/0)
multi_timer_cb 3000
check_run_count prev 0 still 1
check_run_count prev 1 still 1
timer_cb w 0x7fff8973ca98 revents 256
Progress: http://localhost:9000 (0/0)
multi_timer_cb 3000
check_run_count prev 1 still 1
timer_cb w 0x7fff8973ca98 revents 256
Progress: http://localhost:9000 (0/0)
* Operation too slow. Less than 10 bytes/sec transfered the last 3 seconds
Progress: http://localhost:9000 (0/0)
* Closing connection #0
* STATE: PERFORM => COMPLETED handle 0xca8168; (connection #-5000)
sock_cb e 0xc9f5b8 s 6 what 4 cbp 0x7fff8973ca60 sockp 0xca9c40
socket callback: s=6 e=0xc9f5b8 what=REMOVE
remsock
check_run_count prev 1 still 0
REMAINING: 0
DONE: http://localhost:9000 => (28) Operation too slow. Less than 10
bytes/sec transfered the last 3 seconds
-------------------------------------------

In most cases it does not work:

-------- not working ---------------
./evhiperfifo
Creating named pipe "hiper.fifo"
Now, pipe some URL's into > hiper.fifo
Adding easy 0x1ce85b8 to multi 0x1cc5858 (http://localhost:9000)
multi_timer_cb 0
timer_cb w 0x7fff4015d4b8 revents 0
* STATE: INIT => CONNECT handle 0x1cf1168; (connection #-5000)
* About to connect() to localhost port 9000 (#0)
* Trying 127.0.0.1... * connected
* Connected to localhost (127.0.0.1) port 9000 (#0)
* STATE: CONNECT => DO handle 0x1cf1168; (connection #0)
sock_cb e 0x1ce85b8 s 6 what 2 cbp 0x7fff4015d480 sockp (nil)
socket callback: s=6 e=0x1ce85b8 what=OUT Adding data: OUT
setsock
> GET / HTTP/1.1
Host: localhost:9000
Accept: */*

* STATE: DO => DO_DONE handle 0x1cf1168; (connection #0)
sock_cb e 0x1ce85b8 s 6 what 1 cbp 0x7fff4015d480 sockp 0x1cf2c40
socket callback: s=6 e=0x1ce85b8 what=IN Changing action from OUT to IN
setsock
* STATE: DO_DONE => WAITPERFORM handle 0x1cf1168; (connection #0)
* Conn 0 recv pipe 1 inuse 0 athead 1
* STATE: WAITPERFORM => PERFORM handle 0x1cf1168; (connection #0)
Progress: http://localhost:9000 (0/0)
multi_timer_cb 3000
check_run_count prev 0 still 1
check_run_count prev 1 still 1
timer_cb w 0x7fff4015d4b8 revents 256
Progress: http://localhost:9000 (0/0)
multi_timer_cb 3001
check_run_count prev 1 still 1
timer_cb w 0x7fff4015d4b8 revents 256
check_run_count prev 1 still 1
-----------------------------------------

Adding debug statements in multi.c I figured out, for cases when it does
not work, we have 1 entry in the splay tree, for working cases we have 2.
Thats why I called it "loosing timeouts".

The code for "evhiperfifo.c" is attached, basically a port of
hiperfifo.c to use libev instead of libevent, making use of the
curl_multi_socket_action api instead of curl_multi_socket, fixing
check_run_count to list all finished downloads and using the LOW_SPEED
options.

to compile:
gcc evhiperfifo evhiperfifo.c -lcurl -lev

MfG
Markus

Received on 2008-11-20