mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-07-13 02:03:44 +00:00
fix race on disconnect
between the time we check for `is_open` and the actual disconnect, the socket could already have been disconnected by another thread (TOCTOU). Furthermore, the disconnects can race causing a segfault or similar issue in the asio's internals.
This commit is contained in:
+14
-2
@@ -18,6 +18,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@@ -68,8 +69,11 @@ public:
|
||||
std::string GetCarPositionRaw(int Ident);
|
||||
void SetUDPAddr(const ip::udp::endpoint& Addr) { mUDPAddress = Addr; }
|
||||
void SetTCPSock(ip::tcp::socket&& CSock) { mSocket = std::move(CSock); }
|
||||
void Disconnect(std::string_view Reason);
|
||||
bool IsDisconnected() const { return !mSocket.is_open(); }
|
||||
// Returns true only for the thread that actually performs socket shutdown/close.
|
||||
[[nodiscard]] bool Disconnect(std::string_view Reason);
|
||||
bool IsDisconnected() const {
|
||||
return mDisconnectState.load(std::memory_order_acquire) != EDisconnectState::Connected;
|
||||
}
|
||||
// locks
|
||||
void DeleteCar(int Ident);
|
||||
[[nodiscard]] const std::unordered_map<std::string, std::string>& GetIdentifiers() const { return mIdentifiers; }
|
||||
@@ -106,6 +110,12 @@ public:
|
||||
[[nodiscard]] const std::vector<uint8_t>& GetMagic() const { return mMagic; }
|
||||
|
||||
private:
|
||||
enum class EDisconnectState {
|
||||
Connected,
|
||||
Disconnecting,
|
||||
Disconnected
|
||||
};
|
||||
|
||||
void InsertVehicle(int ID, const std::string& Data);
|
||||
|
||||
TServer& mServer;
|
||||
@@ -121,6 +131,8 @@ private:
|
||||
TSetOfVehicleData mVehicleData;
|
||||
SparseArray<std::string> mVehiclePosition;
|
||||
std::string mName = "Unknown Client";
|
||||
// Once disconnect starts, this client is terminal and its socket must be treated as dead.
|
||||
std::atomic<EDisconnectState> mDisconnectState { EDisconnectState::Connected };
|
||||
ip::tcp::socket mSocket;
|
||||
ip::udp::endpoint mUDPAddress {};
|
||||
int mUnicycleID = -1;
|
||||
|
||||
Reference in New Issue
Block a user