curl / Mailing Lists / curl-library / Single Mail


Re: libcurl http2 connection reuse

From: lali .cpp via curl-library <>
Date: Sun, 14 Jan 2018 11:37:13 +0530

Can you help us to create a test source code that reproduces this in a
> decent way that we can use to work on a fix?

Sorry that I forgot to "reply all" taking the conversation off the mailing
list unintentionally. For a minimal client, I have made bare-minimum
modifications in
I am attaching the client(simple_client2.c) and server(server2.go) source
files which reproduce this scenario.

The client gives the server 1 second to respond, the server intentionally
chooses a random value between 0 to 2000 ms to wait before replying to the
client. So sometimes the request doesn't "complete" and so libcurl
"tearsdown" the connection when curl_multi_remove_handle is called(which
ideally it shouldn't for http2)
The client can be run by using this command(after compiling it)
./simple_client 1

For completeness, I am copy-pasting the content of my earlier reply(which
got off the mailing list) and which contains instructions to run server as
well as well as a proposed fix for the problem :-

Thanks for the response. Please find attached files, one for curl based c
client and a golang based http2 server.
The client is not _minimal_ and once you are able to build it you can run
it by :-
./client 1 20 150, here second argument i.e 1 means the number of threads,
third argument i.e 20 means that I want to call http2 server 20 times and
fourth argument i.e 150 is the "timeout" in milliseconds, you can modify
these values.

The server can be run by :- go run server.go(will need go 1.8). The server
when receives a request from client, waits randomly between 10ms to 200 ms
before responding with a 2048 byte payload to the client. You can generate
the certificate and key by using the following commands
openssl genrsa -out localhost.key 2048
openssl req -new -x509 -key localhost.key -out localhost.cert -days 3650
-subj /CN=localhost

So essentially a couple of request would not timeout and some would
timeout. Thereby reproducing the scenario wherein libcurl tearsdown the
underlying TCP connection when the connection is "premature" i.e this
connection was said to be DONE before the entire request operation is

My investigation reveals that the connection gets disconnected when the
curl_multi_remove_handle function is called for the easy_handle; the
connection is in not in the state *CURLM_STATE_COMPLETED* function and this
"premature" connection is finally closed in multi_done function(line 616
file multi.c)

I am attaching the libcurl debug logs(before.log) when I ran the test on
libcurl 7.57.

Thereafter I tried to give a one liner fix(after spending a couple of hours
with the libcurl code), here is the amateur fix I could think of
Modify the conditional check on line 615 of multi.c from
|| premtatur to
(premature && conn->httpversion < 20)

I am also attaching the libcurl debug logs(after.log), with my "fix" which
shows that the same connection gets re-used and libcurl never tearsdown the
underlying TCP conneciton even on "timeout"(i.e connection was said to be
DONE before the entire request operation is complete)

But this is first time I am playing with libcurl code, and I am not very
confident about this fix. So I request you to please help me out here :)

Thanks a lot for your time and patience.



Received on 2018-01-14