From 608eb95284540e1e1ad8b969b6d767a7592647d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 2 Jul 2020 08:11:16 +0300 Subject: [PATCH] MXS-3055: Prevent sending of an extra COM_QUIT If the protocol routes a COM_QUIT packet to the backend, it must not generate a packet when it is shutting down. This could cause unexpected write errors if the backend server managed to close the socket before the write was done. --- include/maxscale/protocol/mysql.hh | 1 + .../protocol/MySQL/mariadbbackend/mysql_backend.cc | 13 +++++++++++-- server/modules/protocol/MySQL/mysql_common.cc | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/maxscale/protocol/mysql.hh b/include/maxscale/protocol/mysql.hh index 5dc4ee79b..4ae7f3a9a 100644 --- a/include/maxscale/protocol/mysql.hh +++ b/include/maxscale/protocol/mysql.hh @@ -340,6 +340,7 @@ typedef struct bool collect_result; /*< Collect the next result set as one buffer */ bool changing_user; bool track_state; /*< Track session state */ + bool send_com_quit; uint32_t num_eof_packets; /*< Encountered eof packet number, used for check * packet type */ bool large_query; /*< Whether to ignore the command byte of the next diff --git a/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc b/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc index af303d157..d50b25fe3 100644 --- a/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc +++ b/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc @@ -1286,6 +1286,12 @@ static int gw_MySQLWrite_backend(DCB* dcb, GWBUF* queue) } else { + + if (cmd == MXS_COM_QUIT) + { + backend_protocol->send_com_quit = false; + } + if (GWBUF_IS_IGNORABLE(queue)) { /** The response to this command should be ignored */ @@ -1398,8 +1404,11 @@ static int gw_backend_close(DCB* dcb) mxb_assert(dcb->session || dcb->persistentstart); MySQLProtocol* proto = (MySQLProtocol*)dcb->protocol; - /** Send COM_QUIT to the backend being closed */ - dcb_write(dcb, mysql_create_com_quit(NULL, 0)); + if (proto->send_com_quit && proto->protocol_auth_state == MXS_AUTH_STATE_COMPLETE) + { + // Send a COM_QUIT to the backend being closed, we haven't routed one to it yet. + dcb_write(dcb, mysql_create_com_quit(NULL, 0)); + } /** Free protocol data */ mysql_protocol_done(dcb); diff --git a/server/modules/protocol/MySQL/mysql_common.cc b/server/modules/protocol/MySQL/mysql_common.cc index 6cb64747c..af501f8f4 100644 --- a/server/modules/protocol/MySQL/mysql_common.cc +++ b/server/modules/protocol/MySQL/mysql_common.cc @@ -64,6 +64,7 @@ MySQLProtocol* mysql_protocol_init(DCB* dcb, int fd) p->num_eof_packets = 0; p->large_query = false; p->track_state = false; + p->send_com_quit = true; /*< Assign fd with protocol */ p->fd = fd; p->owner_dcb = dcb;