You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In my application I'm using libcurl to perform FTP requests via the easy interface. I create a handle with curl_easy_init() and keep it open for as long as I need it. Most of the time the handle will be in idle state. Actual calls to curl_easy_perform() might occur, but sometimes there will be no request at all before the handle is destroyed via curl_easy_cleanup().
curl_easy_cleanup() sends a QUIT command to the FTP server. The server implementation I am using wants to respond to that command by sending Bye on the connection. What I observe now is that if CURLOPT_TIMEOUT is set to some value X and the time span between curl_easy_init() and curl_easy_cleanup() is greater than X (without any curl_easy_perform() in between), libcurl closes the connection immediately after sending the QUIT command, making the FTP server fail to send the Bye because the connection is already closed. I tested with multiple values of CURLOPT_TIMEOUT and I can confirm that the timeout is directly correlated to the observed behavior.
I skimmed through the libcurl sources and it seems that the current timestamp is stored inside the connection handle (conn->now). This is done in only one place and that is in the Curl_setup_conn() function in url.c. The stored timestamp is then used to evaluate the timeout by calculating the difference against the current timestamp in Curl_pp_state_timeout() in pingpong.c.
This tells me that idle time counts towards the timeout which seems unintuitive to me. I don't know where Curl_setup_conn() is called but obviously the stored time is updated whenever a curl_easy_perform() is executed, which is good. That way I can keep the connection open (and fix my problem) by sending periodic NOOPs on the control connection. But in my opinion it should not be necessary in the first place. The timeout should affect the runtime of curl_easy_perform() only.
Maybe I'm using libcurl the wrong way, but I think the behavior is wrong in an application context. It might make sense for command line calls of curl but when using the library functions I would expect that CURLOPT_TIMEOUT is equivalent to a transmit timeout and does not count idle time on the handle.
The issue can be reproduced on Linux and Windows with the latest version of libcurl.
The text was updated successfully, but these errors were encountered:
I can confirm that this is indeed how the timeout value is set and used. The timeout is for "the entire operation" and the commands that are sent when shutting down a connection are also included in that "entire operation" - which in a case like described here is far from obvious and a bit strange.
It would probably make sense to reset the timestamp when curl_easy_cleanup() gets invoked so that a new full timeout period is allowed for the shutdown-sequence. The question is of course if we then will surprise existing application users (who might depend on the current functionality) in a negative way...
The timeout set with CURLOPT_TIMEOUT is no longer used when
disconnecting from one of the pingpong protocols (FTP, IMAP, SMTP,
POP3).
Reported-by: jasal82 on github
Fixes#3264
The timeout set with CURLOPT_TIMEOUT is no longer used when
disconnecting from one of the pingpong protocols (FTP, IMAP, SMTP,
POP3).
Reported-by: jasal82 on github
Fixes#3264
In my application I'm using libcurl to perform FTP requests via the easy interface. I create a handle with
curl_easy_init()
and keep it open for as long as I need it. Most of the time the handle will be in idle state. Actual calls tocurl_easy_perform()
might occur, but sometimes there will be no request at all before the handle is destroyed viacurl_easy_cleanup()
.curl_easy_cleanup()
sends aQUIT
command to the FTP server. The server implementation I am using wants to respond to that command by sendingBye
on the connection. What I observe now is that ifCURLOPT_TIMEOUT
is set to some valueX
and the time span betweencurl_easy_init()
andcurl_easy_cleanup()
is greater thanX
(without anycurl_easy_perform()
in between), libcurl closes the connection immediately after sending theQUIT
command, making the FTP server fail to send theBye
because the connection is already closed. I tested with multiple values ofCURLOPT_TIMEOUT
and I can confirm that the timeout is directly correlated to the observed behavior.I skimmed through the libcurl sources and it seems that the current timestamp is stored inside the connection handle (
conn->now
). This is done in only one place and that is in theCurl_setup_conn()
function inurl.c
. The stored timestamp is then used to evaluate the timeout by calculating the difference against the current timestamp inCurl_pp_state_timeout()
inpingpong.c
.This tells me that idle time counts towards the timeout which seems unintuitive to me. I don't know where
Curl_setup_conn()
is called but obviously the stored time is updated whenever acurl_easy_perform()
is executed, which is good. That way I can keep the connection open (and fix my problem) by sending periodicNOOP
s on the control connection. But in my opinion it should not be necessary in the first place. The timeout should affect the runtime ofcurl_easy_perform()
only.Maybe I'm using libcurl the wrong way, but I think the behavior is wrong in an application context. It might make sense for command line calls of curl but when using the library functions I would expect that
CURLOPT_TIMEOUT
is equivalent to a transmit timeout and does not count idle time on the handle.The issue can be reproduced on Linux and Windows with the latest version of libcurl.
The text was updated successfully, but these errors were encountered: