diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 73da2c2a67..960ca13024 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -126,7 +126,6 @@ namespace OpenRCT2 ~Context() override { window_close_all(); - network_close(); http_dispose(); language_close_all(); object_manager_unload_all_objects(); diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index df9be77768..a68cdee52e 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -137,7 +137,9 @@ Network::Network() Network::~Network() { - Close(); + CloseChatLog(); + CloseServerLog(); + CloseConnection(); } void Network::SetEnvironment(IPlatformEnvironment * env) @@ -165,52 +167,59 @@ bool Network::Init() void Network::Close() { - if (status == NETWORK_STATUS_NONE) + if (status != NETWORK_STATUS_NONE) { - // Already closed. This prevents a call in ~Network() to gfx_invalidate_screen() - // which may no longer be valid on Linux and would cause a segfault. - return; - } + // HACK Because Close() is closed all over the place, it sometimes gets called inside an Update + // call. This then causes disposed data to be accessed. Therefore, save closing until the + // end of the update loop. + if (_closeLock) + { + _requireClose = true; + return; + } - // HACK Because Close() is closed all over the place, it sometimes gets called inside an Update - // call. This then causes disposed data to be accessed. Therefore, save closing until the - // end of the update loop. - if (_closeLock) { - _requireClose = true; - return; - } + CloseChatLog(); + CloseServerLog(); + CloseConnection(); - if (mode == NETWORK_MODE_CLIENT) { + client_connection_list.clear(); + game_command_queue.clear(); + player_list.clear(); + group_list.clear(); + + gfx_invalidate_screen(); + + _requireClose = false; + } +} + +void Network::CloseConnection() +{ + if (mode == NETWORK_MODE_CLIENT) + { delete server_connection->Socket; server_connection->Socket = nullptr; - } else if (mode == NETWORK_MODE_SERVER) { + } + else if (mode == NETWORK_MODE_SERVER) + { delete listening_socket; listening_socket = nullptr; delete _advertiser; _advertiser = nullptr; } - CloseChatLog(); - CloseServerLog(); - mode = NETWORK_MODE_NONE; status = NETWORK_STATUS_NONE; _lastConnectStatus = SOCKET_STATUS_CLOSED; - server_connection->AuthStatus = NETWORK_AUTH_NONE; - server_connection->InboundPacket.Clear(); - server_connection->SetLastDisconnectReason(nullptr); - SafeDelete(server_connection); - - client_connection_list.clear(); - game_command_queue.clear(); - player_list.clear(); - group_list.clear(); + if (server_connection != nullptr) + { + server_connection->AuthStatus = NETWORK_AUTH_NONE; + server_connection->InboundPacket.Clear(); + server_connection->SetLastDisconnectReason(nullptr); + delete server_connection; + } DisposeWSA(); - - gfx_invalidate_screen(); - - _requireClose = false; } bool Network::BeginClient(const char* host, uint16 port) diff --git a/src/openrct2/network/network.h b/src/openrct2/network/network.h index 4520f6745d..bb10a743cd 100644 --- a/src/openrct2/network/network.h +++ b/src/openrct2/network/network.h @@ -174,6 +174,8 @@ public: std::string ServerProviderWebsite; private: + void CloseConnection(); + bool ProcessConnection(NetworkConnection& connection); void ProcessPacket(NetworkConnection& connection, NetworkPacket& packet); void AddClient(ITcpSocket * socket);