diff --git a/include/maxscale/dcb.h b/include/maxscale/dcb.h index 21933b795..411ab8bb3 100644 --- a/include/maxscale/dcb.h +++ b/include/maxscale/dcb.h @@ -229,7 +229,8 @@ typedef struct dcb uint32_t n_close; /** How many times dcb_close has been called. */ char* path; /** If a Unix socket, the path it was bound to. */ - uint64_t m_uid; /**< Unique identifier for this DCB */ + uint64_t m_uid; /**< Unique identifier for this DCB */ + bool is_fake_event; } DCB; /** diff --git a/server/core/dcb.cc b/server/core/dcb.cc index 456b081cf..d6828cd3f 100644 --- a/server/core/dcb.cc +++ b/server/core/dcb.cc @@ -204,6 +204,7 @@ DCB* dcb_alloc(dcb_role_t role, SERV_LISTENER* listener) newdcb->low_water = config_writeq_low_water(); newdcb->high_water = config_writeq_high_water(); newdcb->m_uid = this_unit.uid_generator.fetch_add(1, std::memory_order_relaxed); + newdcb->is_fake_event = false; if (role == DCB_ROLE_SERVICE_LISTENER) { @@ -2062,7 +2063,9 @@ static void dcb_hangup_foreach_worker(MXB_WORKER* worker, struct server* server) { this_thread.current_dcb = dcb; dcb->flags |= DCBF_HUNG; + dcb->is_fake_event = true; dcb->func.hangup(dcb); + dcb->is_fake_event = false; } } @@ -3249,7 +3252,9 @@ static uint32_t dcb_handler(DCB* dcb, uint32_t events) events = dcb->fake_event; dcb->fake_event = 0; + dcb->is_fake_event = true; rv |= dcb_process_poll_events(dcb, events); + dcb->is_fake_event = false; } this_thread.current_dcb = NULL; diff --git a/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc b/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc index d00eef6b7..ef904c4f4 100644 --- a/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc +++ b/server/modules/protocol/MySQL/mariadbbackend/mysql_backend.cc @@ -25,6 +25,8 @@ #include #include +#include + /* * MySQL Protocol module for handling the protocol between the gateway * and the backend MySQL database. @@ -585,6 +587,23 @@ static int gw_read_backend_event(DCB* dcb) return rc; } +static std::string get_detailed_error(DCB* dcb) +{ + std::ostringstream ss; + + if (int err = gw_getsockerrno(dcb->fd)) + { + ss << " (" << err << ", " << mxs_strerror(err) << ")"; + } + else if (dcb->is_fake_event) + { + // Fake events should not have TCP socket errors + ss << " (Generated event)"; + } + + return ss.str(); +} + static void do_handle_error(DCB* dcb, mxs_error_action_t action, const char* errmsg) { bool succp = true; @@ -592,7 +611,7 @@ static void do_handle_error(DCB* dcb, mxs_error_action_t action, const char* err if (!dcb->dcb_errhandle_called) { - GWBUF* errbuf = mysql_create_custom_error(1, 0, errmsg); + GWBUF* errbuf = mysql_create_custom_error(1, 0, (errmsg + get_detailed_error(dcb)).c_str()); MXS_ROUTER_SESSION* rsession = static_cast(session->router_session); MXS_ROUTER_OBJECT* router = session->service->router; MXS_ROUTER* router_instance = session->service->router_instance; @@ -1340,7 +1359,7 @@ static int gw_error_backend_event(DCB* dcb) } else { - do_handle_error(dcb, ERRACT_NEW_CONNECTION, "Lost connection to backend server."); + do_handle_error(dcb, ERRACT_NEW_CONNECTION, "Lost connection to backend server: network error"); } return 1; @@ -1381,7 +1400,8 @@ static int gw_backend_hangup(DCB* dcb) } else { - do_handle_error(dcb, ERRACT_NEW_CONNECTION, "Lost connection to backend server."); + do_handle_error(dcb, ERRACT_NEW_CONNECTION, + "Lost connection to backend server: connection closed by peer"); } return 1;