From 4969bd8301af17bec21b718cd8364beaedfb8ccd Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Thu, 24 Apr 2025 19:42:23 +0500 Subject: [PATCH] PQconnectPoll can file descriptor (FD) during the connection process. We need to check whether FD has changed and, if so, update it in the thread's poll array. --- lib/PgSQL_Connection.cpp | 10 ++++++++-- lib/PgSQL_Session.cpp | 13 ++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/PgSQL_Connection.cpp b/lib/PgSQL_Connection.cpp index 68baf89da..cb1517f9e 100644 --- a/lib/PgSQL_Connection.cpp +++ b/lib/PgSQL_Connection.cpp @@ -884,7 +884,7 @@ void PgSQL_Connection::connect_cont(short event) { case PGRES_POLLING_WRITING: async_exit_status = PG_EVENT_WRITE; break; - case PGRES_POLLING_ACTIVE: + case PGRES_POLLING_ACTIVE: // Not used case PGRES_POLLING_READING: async_exit_status = PG_EVENT_READ; break; @@ -897,7 +897,13 @@ void PgSQL_Connection::connect_cont(short event) { const PGresult* result = PQgetResultFromPGconn(pgsql_conn); set_error_from_result(result); proxy_error("Connect failed. %s\n", get_error_code_with_message().c_str()); - return; + } + int current_fd = PQsocket(pgsql_conn); + if (current_fd != fd) { + proxy_warning("PgSQL Connection FD has been changed by PQconnectPoll(). oldFD:%d newFD:%d\n", fd, current_fd); + proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "PgSQL Connection FD has been changed by PQconnectPoll()" + "Session=%p, Conn=%p, myds=%p, oldFD=%d, newFD=%d\n", myds->sess, this, myds, fd, current_fd); + fd = current_fd; } } diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index c09dce42c..5426a49ce 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -1744,10 +1744,21 @@ bool PgSQL_Session::handler_again___status_CONNECTING_SERVER(int* _rc) { if (myds->mypolls == NULL) { // connection yet not in mypolls myds->assign_fd_from_mysql_conn(); - thread->mypolls.add(POLLIN | POLLOUT, mybe->server_myds->fd, mybe->server_myds, curtime); + thread->mypolls.add(POLLIN | POLLOUT, myds->fd, myds, curtime); if (mirror) { PROXY_TRACE(); } + } else { + // See Issue#4919 (https://github.com/sysown/proxysql/issues/4919) + // File descriptor was already set previously. Let's verify if it has changed + if (myds->fd != myconn->fd) + { + // PQconnectPoll has changed the file descriptor (FD) during the connection process. + // We need to update the new FD in mypolls, replacing the old one, + // Note: previous FD is closed by PQconnectPoll + myds->assign_fd_from_mysql_conn(); + thread->mypolls.update_fd_at_index(myds->poll_fds_idx, myds->fd); + } } switch (rc) { case 0: