summaryrefslogtreecommitdiff
path: root/lib/cf-socket.c
diff options
context:
space:
mode:
authorStefan Eissing <stefan@eissing.org>2023-03-01 13:05:09 +0100
committerDaniel Stenberg <daniel@haxx.se>2023-03-02 09:03:06 +0100
commit9fd2d5aa722d00c67b659938428c3b1047e949a6 (patch)
treeb3d62fb8cebb5e83b9922b959a54d11a3c0715f2 /lib/cf-socket.c
parent9deebd311b167bbb7866c4a223934a8e25dfb78c (diff)
downloadcurl-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.c36
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;
}