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<T>(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: #25271
(cherry picked from commit 30d424e0d3)
This commit is contained in:
Dario Mirovic
2025-07-15 20:25:20 +02:00
parent 918d4ab5fb
commit 0679a7bb78

View File

@@ -675,17 +675,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<exceptions::cassandra_exception>(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<std::exception>(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()));