-
-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Description
I did this
We're experiencing the following sequence of events:
- We perform a request that fails with
CURLE_SEND_FAIL_REWIND(errno 65). - We reset the handle using
curl_easy_reset(). - We perform another request, which immediately returns with the same
CURLE_SEND_FAIL_REWINDerror, before curl has even tried to connect.
We would expect that the curl_easy_reset() call would completely reset the handle, clearing the rewind failure on the request, so that subsequent requests using this handle work. I've created a failing testcase that reproduces this behaviour.
For the request in the first step, we're using the CURLOPT_UPLOAD option, and to supply the request body we have set CURLOPT_READFUNCTION but not CURLOPT_SEEKFUNCTION (this is due to ext-curl in PHP, which always sets the read function but doesn't support setting the seek function). We have enabled following redirects on this request using CURLOPT_FOLLOWLOCATION, and the server returns a HTTP 307 redirect. In this situation, it makes total sense that curl can't rewind the body to follow the redirect and returns a CURLE_SEND_FAIL_REWIND - that's not the bug.
Next, we call curl_easy_reset() to reset the handle. According to the documentation, this should bring the handle to the same state as when it was just created with curl_easy_init(). To validate this is a problem with curl_easy_reset(), we've tried replacing this call with a new call to curl_easy_init(), and that fixes the problem.
It doesn't matter what kind of request the request in the third step is: a GET will fail, as will a request using CURLOPT_POSTFIELDS or CURLOPT_READFUNCTION.
I tried to debug this a little bit, and I can confirm that adding req->rewind_read = FALSE; (like this) in Curl_req_hard_reset() fixes the problem. However, I'm not familiar enough with the curl code to say whether this is the best way to fix this, and whether this wouldn't break other scenarios. I'm happy to submit a PR with this change and the testcase if you agree this is the way to go.
I expected the following
See above - for the curl handle to be usable for a second request again after a CURLE_SEND_FAIL_REWIND error.
curl/libcurl version
Reproduced both on curl v8.14.1 and latest master (commit 034612c).
operating system
Linux L-F4FWVJ 6.8.0-71-generic #71-Ubuntu SMP PREEMPT_DYNAMIC Tue Jul 22 16:52:38 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Also reproducable using the curl inside Alpine v3.22 Docker containers.