Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idle time seems to count towards timeout configured in CURLOPT_TIMEOUT #3264

Closed
jasal82 opened this issue Nov 13, 2018 · 2 comments
Closed
Assignees

Comments

@jasal82
Copy link

jasal82 commented Nov 13, 2018

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.

@bagder
Copy link
Member

bagder commented Nov 13, 2018

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...

Whatever we decide, we should document this.

@bagder bagder self-assigned this Dec 8, 2018
bagder added a commit that referenced this issue Dec 14, 2018
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
bagder added a commit that referenced this issue Dec 14, 2018
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
@bagder
Copy link
Member

bagder commented Dec 14, 2018

I've made sure that the timeout is not used anymore when in disconnect "phase". Please have a go and see if #3374 fixes the problem for you!

@bagder bagder closed this as completed in 154a17b Dec 17, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Mar 17, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

2 participants