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:
Stefan Eissing 2023-03-01 13:05:09 +01:00 committed by Daniel Stenberg
parent 9deebd311b
commit 9fd2d5aa72
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 25 additions and 20 deletions

View File

@ -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;
}

View File

@ -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 = {