From: Stefan Eissing Date: Tue, 25 Jun 2024 09:35:48 +0000 (+0200) Subject: multi: multi_getsock(), check correct socket X-Git-Tag: curl-8_9_0~194 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=def99d850792ded8ea16614a200ac76534cf05f5;p=thirdparty%2Fcurl.git multi: multi_getsock(), check correct socket - in phase CONNECTING/TUNNELING/PROTOCONNECT, retrieve the socket from the connection filters and do not rely on `conn->sockfd` being already set by the transfer. - this applies to the default behaviour, a protocol handler may override this via its callbacks. - add a warning message in multi_getsock() when the transfer is expected to have something in its pollset, but instead it is empty. Reported-by: saurabhsingh-dev on github Fixes #13998 Closes #14011 --- diff --git a/lib/multi.c b/lib/multi.c index fad1899fa2..421db8465c 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -1024,12 +1024,14 @@ void Curl_attach_connection(struct Curl_easy *data, static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks) { struct connectdata *conn = data->conn; - (void)socks; - /* Not using `conn->sockfd` as `Curl_xfer_setup()` initializes - * that *after* the connect. */ - if(conn && conn->sock[FIRSTSOCKET] != CURL_SOCKET_BAD) { + curl_socket_t sockfd; + + if(!conn) + return GETSOCK_BLANK; + sockfd = Curl_conn_get_socket(data, FIRSTSOCKET); + if(sockfd != CURL_SOCKET_BAD) { /* Default is to wait to something from the server */ - socks[0] = conn->sock[FIRSTSOCKET]; + socks[0] = sockfd; return GETSOCK_READSOCK(0); } return GETSOCK_BLANK; @@ -1038,11 +1040,16 @@ static int connecting_getsock(struct Curl_easy *data, curl_socket_t *socks) static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks) { struct connectdata *conn = data->conn; - if(conn && conn->handler->proto_getsock) + curl_socket_t sockfd; + + if(!conn) + return GETSOCK_BLANK; + if(conn->handler->proto_getsock) return conn->handler->proto_getsock(data, conn, socks); - else if(conn && conn->sockfd != CURL_SOCKET_BAD) { + sockfd = Curl_conn_get_socket(data, FIRSTSOCKET); + if(sockfd != CURL_SOCKET_BAD) { /* Default is to wait to something from the server */ - socks[0] = conn->sockfd; + socks[0] = sockfd; return GETSOCK_READSOCK(0); } return GETSOCK_BLANK; @@ -1051,9 +1058,11 @@ static int protocol_getsock(struct Curl_easy *data, curl_socket_t *socks) static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks) { struct connectdata *conn = data->conn; - if(conn && conn->handler->domore_getsock) + if(!conn) + return GETSOCK_BLANK; + if(conn->handler->domore_getsock) return conn->handler->domore_getsock(data, conn, socks); - else if(conn && conn->sockfd != CURL_SOCKET_BAD) { + else if(conn->sockfd != CURL_SOCKET_BAD) { /* Default is that we want to send something to the server */ socks[0] = conn->sockfd; return GETSOCK_WRITESOCK(0); @@ -1064,9 +1073,11 @@ static int domore_getsock(struct Curl_easy *data, curl_socket_t *socks) static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks) { struct connectdata *conn = data->conn; - if(conn && conn->handler->doing_getsock) + if(!conn) + return GETSOCK_BLANK; + if(conn->handler->doing_getsock) return conn->handler->doing_getsock(data, conn, socks); - else if(conn && conn->sockfd != CURL_SOCKET_BAD) { + else if(conn->sockfd != CURL_SOCKET_BAD) { /* Default is that we want to send something to the server */ socks[0] = conn->sockfd; return GETSOCK_WRITESOCK(0); @@ -1077,7 +1088,6 @@ static int doing_getsock(struct Curl_easy *data, curl_socket_t *socks) static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock) { struct connectdata *conn = data->conn; - if(!conn) return GETSOCK_BLANK; else if(conn->handler->perform_getsock) @@ -1114,6 +1124,7 @@ static int perform_getsock(struct Curl_easy *data, curl_socket_t *sock) static void multi_getsock(struct Curl_easy *data, struct easy_pollset *ps) { + bool expect_sockets = TRUE; /* The no connection case can happen when this is called from curl_multi_remove_handle() => singlesocket() => multi_getsock(). */ @@ -1127,6 +1138,7 @@ static void multi_getsock(struct Curl_easy *data, case MSTATE_SETUP: case MSTATE_CONNECT: /* nothing to poll for yet */ + expect_sockets = FALSE; break; case MSTATE_RESOLVING: @@ -1165,19 +1177,26 @@ static void multi_getsock(struct Curl_easy *data, case MSTATE_RATELIMITING: /* we need to let time pass, ignore socket(s) */ + expect_sockets = FALSE; break; case MSTATE_DONE: case MSTATE_COMPLETED: case MSTATE_MSGSENT: /* nothing more to poll for */ + expect_sockets = FALSE; break; default: failf(data, "multi_getsock: unexpected multi state %d", data->mstate); DEBUGASSERT(0); + expect_sockets = FALSE; break; } + + if(expect_sockets && !ps->num && !Curl_xfer_is_blocked(data)) { + infof(data, "WARNING: no socket in pollset, transfer may stall!"); + } } CURLMcode curl_multi_fdset(struct Curl_multi *multi,