protocol handler blocking disconnect workaround
- set the default shutdown timeout of 2 seconds for the internal admin handle when using that to disconnect the protocol - pingpong: add checking the over all timeout of the transfer during disconnect - pingpong: on poll timeout in blocking wait, error with CURLE_OPERATION_TIMEDOUT when disconnecting - multi: readd the timeout/signal "inheritance" of added transfers to the admin handle - as it was before.
This commit is contained in:
parent
5432614ed3
commit
aa3ede6d27
@ -63,7 +63,14 @@ static void cshutdn_run_conn_handler(struct Curl_easy *data,
|
||||
Curl_http_auth_cleanup_negotiate(conn);
|
||||
|
||||
if(conn->handler && conn->handler->disconnect) {
|
||||
unsigned int timeout_ms = data->set.server_response_timeout;
|
||||
/* Some disconnect handlers do a blocking wait on server responses.
|
||||
* FTP/IMAP/SMTP and SFTP are among them. When using the internal
|
||||
* handle, set an overall short timeout so we do not hang for the
|
||||
* default 120 seconds. */
|
||||
if(data->state.internal) {
|
||||
data->set.timeout = DEFAULT_SHUTDOWN_TIMEOUT_MS;
|
||||
(void)Curl_pgrsTime(data, TIMER_STARTOP);
|
||||
}
|
||||
|
||||
/* This is set if protocol-specific cleanups should be made */
|
||||
DEBUGF(infof(data, "connection #%" FMT_OFF_T
|
||||
@ -71,9 +78,7 @@ static void cshutdn_run_conn_handler(struct Curl_easy *data,
|
||||
conn->connection_id, conn->bits.aborted));
|
||||
/* There are protocol handlers that block on retrieving
|
||||
* server responses here (FTP). Set a short timeout. */
|
||||
data->set.server_response_timeout = CURLMIN(timeout_ms, 2 * 1000);
|
||||
conn->handler->disconnect(data, conn, conn->bits.aborted);
|
||||
data->set.server_response_timeout = timeout_ms;
|
||||
}
|
||||
|
||||
/* possible left-overs from the async name resolvers */
|
||||
|
||||
@ -3132,6 +3132,8 @@ static CURLcode ftp_block_statemach(struct Curl_easy *data,
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
while(ftpc->state != FTP_STOP) {
|
||||
if(ftpc->shutdown)
|
||||
CURL_TRC_FTP(data, "in shutdown, waiting for server response");
|
||||
result = Curl_pp_statemach(data, pp, TRUE, TRUE /* disconnecting */);
|
||||
if(result)
|
||||
break;
|
||||
@ -4043,6 +4045,7 @@ static CURLcode ftp_quit(struct Curl_easy *data, struct connectdata *conn)
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(conn->proto.ftpc.ctl_valid) {
|
||||
CURL_TRC_FTP(data, "sending QUIT to close session");
|
||||
result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "QUIT");
|
||||
if(result) {
|
||||
failf(data, "Failure sending QUIT command: %s",
|
||||
|
||||
@ -417,6 +417,15 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
|
||||
Curl_cpool_xfer_init(data);
|
||||
multi_warn_debug(multi, data);
|
||||
|
||||
/* The admin handle only ever has default timeouts set. To improve the
|
||||
state somewhat we clone the timeouts from each added handle so that the
|
||||
admin handle always has the same timeouts as the most recently added
|
||||
easy handle. */
|
||||
multi->admin->set.timeout = data->set.timeout;
|
||||
multi->admin->set.server_response_timeout =
|
||||
data->set.server_response_timeout;
|
||||
multi->admin->set.no_signal = data->set.no_signal;
|
||||
|
||||
CURL_TRC_M(data, "added, transfers=%u", multi->num_easy);
|
||||
return CURLM_OK;
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "sendf.h"
|
||||
#include "select.h"
|
||||
#include "progress.h"
|
||||
@ -74,6 +75,11 @@ timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
|
||||
timeout_ms = CURLMIN(timeout_ms, timeout2_ms);
|
||||
}
|
||||
|
||||
if(disconnecting) {
|
||||
timediff_t total_left_ms = Curl_timeleft(data, NULL, FALSE);
|
||||
timeout_ms = CURLMIN(timeout_ms, CURLMAX(total_left_ms, 0));
|
||||
}
|
||||
|
||||
return timeout_ms;
|
||||
}
|
||||
|
||||
@ -96,6 +102,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
|
||||
return CURLE_OPERATION_TIMEDOUT; /* already too little time */
|
||||
}
|
||||
|
||||
DEBUGF(infof(data, "pp_statematch, timeout=%" FMT_TIMEDIFF_T, timeout_ms));
|
||||
if(block) {
|
||||
interval_ms = 1000; /* use 1 second timeout intervals */
|
||||
if(timeout_ms < interval_ms)
|
||||
@ -135,6 +142,8 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
|
||||
}
|
||||
else if(rc)
|
||||
result = pp->statemachine(data, data->conn);
|
||||
else if(disconnecting)
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user