mirror of
https://github.com/curl/curl.git
synced 2025-02-23 15:10:03 +08:00
socket: detect "dead" connections better, e.g. not fit for reuse
- refs #10646 where reuse was attempted on closed connections in the cache, leading to an exhaustion of retries on a transfer - the mistake was that poll events like POLLHUP, POLLERR, etc were regarded as "not dead". - change cf-socket filter check to regard such events as inidication of corpsiness. - vtls filter checks: fixed interpretation of backend check result when inconclusive to interrogate status further down the filter chain. Reported-by: SendSonS on github Fixes #10646 Closes #10652
This commit is contained in:
parent
9deebd311b
commit
9fd2d5aa72
@ -1468,35 +1468,33 @@ static bool cf_socket_conn_is_alive(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
int sval;
|
||||
struct pollfd pfd[1];
|
||||
int r;
|
||||
|
||||
(void)data;
|
||||
if(!ctx || ctx->sock == CURL_SOCKET_BAD)
|
||||
return FALSE;
|
||||
|
||||
sval = SOCKET_READABLE(ctx->sock, 0);
|
||||
if(sval == 0) {
|
||||
/* timeout */
|
||||
return TRUE;
|
||||
}
|
||||
else if(sval & CURL_CSELECT_ERR) {
|
||||
/* socket is in an error state */
|
||||
/* Check with 0 timeout if there are any events pending on the socket */
|
||||
pfd[0].fd = ctx->sock;
|
||||
pfd[0].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI;
|
||||
pfd[0].revents = 0;
|
||||
|
||||
r = Curl_poll(pfd, 1, 0);
|
||||
if(r < 0) {
|
||||
DEBUGF(LOG_CF(data, cf, "is_alive: poll error, assume dead"));
|
||||
return FALSE;
|
||||
}
|
||||
else if(sval & CURL_CSELECT_IN) {
|
||||
/* readable with no error. could still be closed */
|
||||
/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
|
||||
#ifdef MSG_PEEK
|
||||
/* use the socket */
|
||||
char buf;
|
||||
if(recv((RECV_TYPE_ARG1)ctx->sock, (RECV_TYPE_ARG2)&buf,
|
||||
(RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
|
||||
return FALSE; /* FIN received */
|
||||
}
|
||||
#endif
|
||||
else if(r == 0) {
|
||||
DEBUGF(LOG_CF(data, cf, "is_alive: poll timeout, assume alive"));
|
||||
return TRUE;
|
||||
}
|
||||
else if(pfd[0].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) {
|
||||
DEBUGF(LOG_CF(data, cf, "is_alive: err/hup/etc events, assume dead"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DEBUGF(LOG_CF(data, cf, "is_alive: valid events, looks alive"));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1649,7 +1649,14 @@ static bool cf_ssl_is_alive(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
CF_DATA_SAVE(save, cf, data);
|
||||
result = Curl_ssl->check_cxn(cf, data) != 0;
|
||||
CF_DATA_RESTORE(cf, save);
|
||||
return result;
|
||||
if(result > 0)
|
||||
return TRUE;
|
||||
if(result == 0)
|
||||
return FALSE;
|
||||
/* ssl backend does not know */
|
||||
return cf->next?
|
||||
cf->next->cft->is_alive(cf->next, data) :
|
||||
FALSE; /* pessimistic in absence of data */
|
||||
}
|
||||
|
||||
struct Curl_cftype Curl_cft_ssl = {
|
||||
|
Loading…
Reference in New Issue
Block a user