diff options
author | Stefan Eissing <stefan@eissing.org> | 2023-03-01 13:05:09 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2023-03-02 09:03:06 +0100 |
commit | 9fd2d5aa722d00c67b659938428c3b1047e949a6 (patch) | |
tree | b3d62fb8cebb5e83b9922b959a54d11a3c0715f2 /lib/cf-socket.c | |
parent | 9deebd311b167bbb7866c4a223934a8e25dfb78c (diff) | |
download | curl-9fd2d5aa722d00c67b659938428c3b1047e949a6.tar.gz |
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
Diffstat (limited to 'lib/cf-socket.c')
-rw-r--r-- | lib/cf-socket.c | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/lib/cf-socket.c b/lib/cf-socket.c index d41206488..f523b1332 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -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; } |