Buy commercial curl support. We
help you work out your issues, debug your libcurl applications, use the API,
port to new platforms, add new features and more. With a team lead by the
curl founder Daniel himself.
Wrong connection reuse case for Share interface
- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]
From: Dmitry Karpov via curl-library <curl-library_at_lists.haxx.se>
Date: Wed, 1 Jul 2026 00:51:27 +0000
Hi Folks,
I found one use case for share interface when a next transfer using the same share handle may use abandoned active connection from the previous transfer which wasn't completed.
The scenario is following:
* Create share handle with CURL_LOCK_DATA_CONNECT option.
* Create easy handle and set share via CURLOPT_SHARE option.
* Create multi-handle and add easy handle to it.
* Run the transfer using multi interface to some point where it will be abandoned (i.e. application may make this decision due to lack of space where to write incoming data etc)
* Set share to NULL on "abandoned" easy handle to avoid using the share on that transfer further and remove it from the multi handle (via curl_multi_remove_handle()).
* Create a new easy handle, set the same share via CURLOPT_SHARE option, add easy handle to the multi-handle and run it.
On the last step, the new transfer may reuse the connection with partially received data from the previously abandoned transfer instead of creating a new one and get "weird server reply" error.
This happens because when share is set to NULL via CURLOPT_SHARE option, it calls the Curl_share_easy_unlink() function which just detaches the connection, but not closes it:
CURLcode Curl_share_easy_unlink(struct Curl_easy *data)
{
...
/* If data has a connection from this share, detach it. */
if(data->conn && (share->specifier & (1 << CURL_LOCK_DATA_CONNECT)))
Curl_detach_connection(data);
...
}
So, when curl_multi_remove_handle() is called later, it doesn't close the connection for the premature finished transfer because the connection was detached,
and thus active connection may be taken from the connection pool own by the share and wrongly reused.
I think the Curl_share_easy_unlink() should close the active connection if it is called on some prematurely abandoned transfer.
I discovered this on the later libcurl versions (8.19+), the older versions like 8.6.0 which I used before don't have this issue, so it may be perceived as a regression from the earlier builds.
It is interesting that sometimes libcurl may avoid reusing the connection in such cases as it detects it as "dead" even though it doesn't close it explicitly,
which allowed my connection sharing to pass in some cases and suspect flakiness.
Thanks!
Dmitry Karpov
Date: Wed, 1 Jul 2026 00:51:27 +0000
Hi Folks,
I found one use case for share interface when a next transfer using the same share handle may use abandoned active connection from the previous transfer which wasn't completed.
The scenario is following:
* Create share handle with CURL_LOCK_DATA_CONNECT option.
* Create easy handle and set share via CURLOPT_SHARE option.
* Create multi-handle and add easy handle to it.
* Run the transfer using multi interface to some point where it will be abandoned (i.e. application may make this decision due to lack of space where to write incoming data etc)
* Set share to NULL on "abandoned" easy handle to avoid using the share on that transfer further and remove it from the multi handle (via curl_multi_remove_handle()).
* Create a new easy handle, set the same share via CURLOPT_SHARE option, add easy handle to the multi-handle and run it.
On the last step, the new transfer may reuse the connection with partially received data from the previously abandoned transfer instead of creating a new one and get "weird server reply" error.
This happens because when share is set to NULL via CURLOPT_SHARE option, it calls the Curl_share_easy_unlink() function which just detaches the connection, but not closes it:
CURLcode Curl_share_easy_unlink(struct Curl_easy *data)
{
...
/* If data has a connection from this share, detach it. */
if(data->conn && (share->specifier & (1 << CURL_LOCK_DATA_CONNECT)))
Curl_detach_connection(data);
...
}
So, when curl_multi_remove_handle() is called later, it doesn't close the connection for the premature finished transfer because the connection was detached,
and thus active connection may be taken from the connection pool own by the share and wrongly reused.
I think the Curl_share_easy_unlink() should close the active connection if it is called on some prematurely abandoned transfer.
I discovered this on the later libcurl versions (8.19+), the older versions like 8.6.0 which I used before don't have this issue, so it may be perceived as a regression from the earlier builds.
It is interesting that sometimes libcurl may avoid reusing the connection in such cases as it detects it as "dead" even though it doesn't close it explicitly,
which allowed my connection sharing to pass in some cases and suspect flakiness.
Thanks!
Dmitry Karpov
-- Unsubscribe: https://lists.haxx.se/mailman/listinfo/curl-library Etiquette: https://curl.se/mail/etiquette.htmlReceived on 2026-07-01