From 2fbcdfd4b4a9ccd792254cf11e2a7a73d7c9fdb7 Mon Sep 17 00:00:00 2001 From: Dario Mirovic Date: Tue, 15 Jul 2025 20:25:20 +0200 Subject: [PATCH] transport/server: avoid exception-throw overhead in handle_error Previously, connection::handle_error always called f.get() inside a try/catch, forcing every failed future to throw and immediately catch an exception just to classify it. This change eliminates that extra throw/catch cycle by first checking f.failed(), getting the stored std::exception_ptr via f.get_exception(), and then dispatching on its type via utils::try_catch(eptr). The error-response logic is not changed - cassandra_exception, std::exception, and unknown exceptions are caught and processed, and any exceptions thrown by write_response while handling those exceptions continues to escape handle_error. Refs: #24567 Fixes: #25273 (cherry picked from commit 30d424e0d3468a8566adcd669f5f02bd5c011bd0) --- transport/server.cc | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/transport/server.cc b/transport/server.cc index 870f6d18d7..598dd1e1c9 100644 --- a/transport/server.cc +++ b/transport/server.cc @@ -664,17 +664,21 @@ thread_local cql_server::connection::execution_stage_type cql_server::connection::_process_request_stage{"transport", &connection::process_request_one}; void cql_server::connection::handle_error(future<>&& f) { - try { - f.get(); - } catch (const exceptions::cassandra_exception& ex) { - clogger.debug("{}: connection error, code {}, message [{}]", _client_state.get_remote_address(), ex.code(), ex.what()); - try { ++_server._stats.errors[ex.code()]; } catch(...) {} - write_response(make_error(0, ex.code(), ex.what(), tracing::trace_state_ptr())); - } catch (std::exception& ex) { - clogger.debug("{}: connection error, message [{}]", _client_state.get_remote_address(), ex.what()); + if (!f.failed()) { + return; + } + + std::exception_ptr eptr = f.get_exception(); + + if (auto* ex = try_catch(eptr)) { + clogger.debug("{}: connection error, code {}, message [{}]", _client_state.get_remote_address(), ex->code(), ex->what()); + try { ++_server._stats.errors[ex->code()]; } catch(...) {} + write_response(make_error(0, ex->code(), ex->what(), tracing::trace_state_ptr())); + } else if (auto* ex = try_catch(eptr)) { + clogger.debug("{}: connection error, message [{}]", _client_state.get_remote_address(), ex->what()); try { ++_server._stats.errors[exceptions::exception_code::SERVER_ERROR]; } catch(...) {} - write_response(make_error(0, exceptions::exception_code::SERVER_ERROR, ex.what(), tracing::trace_state_ptr())); - } catch (...) { + write_response(make_error(0, exceptions::exception_code::SERVER_ERROR, ex->what(), tracing::trace_state_ptr())); + } else { clogger.debug("{}: connection error, unknown error", _client_state.get_remote_address()); try { ++_server._stats.errors[exceptions::exception_code::SERVER_ERROR]; } catch(...) {} write_response(make_error(0, exceptions::exception_code::SERVER_ERROR, "unknown error", tracing::trace_state_ptr()));