diff --git a/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp b/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp index f162a2e8637..71fb24a8e0a 100644 --- a/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp +++ b/LibCarla/source/carla/streaming/detail/tcp/ServerSession.cpp @@ -135,6 +135,16 @@ namespace tcp { } void ServerSession::CloseNow(boost::system::error_code ec) { + // Guard against double-close. CloseNow() can be reached more than once for + // the same session: the deadline timer firing, an async read/write + // completing with an error, and an explicit Close() can all race. Without + // this guard the session invokes _on_closed twice, which calls + // DisconnectSession twice on the stream state, tripping the DEBUG_ASSERT in + // MultiStreamState::DisconnectSession (and corrupting session bookkeeping + // in release builds). + if (_is_closed.exchange(true)) { + return; + } _deadline.cancel(); if (!ec) { diff --git a/LibCarla/source/carla/streaming/detail/tcp/ServerSession.h b/LibCarla/source/carla/streaming/detail/tcp/ServerSession.h index 5cc0f4ddd36..1cb54d26a02 100644 --- a/LibCarla/source/carla/streaming/detail/tcp/ServerSession.h +++ b/LibCarla/source/carla/streaming/detail/tcp/ServerSession.h @@ -22,6 +22,8 @@ # pragma clang diagnostic pop #endif +#include + namespace carla { namespace streaming { namespace detail { @@ -81,6 +83,8 @@ namespace tcp { callback_function_type _on_closed; bool _is_writing = false; + + std::atomic_bool _is_closed{false}; }; } // namespace tcp