Fix race between network client disconnect and network window deletion
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
#include "../network_internal.h"
|
#include "../network_internal.h"
|
||||||
#include "../../debug.h"
|
#include "../../debug.h"
|
||||||
#include "../../error.h"
|
#include "../../error.h"
|
||||||
|
#include "../../window_func.h"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
@@ -109,6 +110,7 @@ NetworkRecvStatus NetworkGameSocketHandler::CloseConnection(bool error)
|
|||||||
if (!_network_server && _networking) {
|
if (!_network_server && _networking) {
|
||||||
extern void ClientNetworkEmergencySave(); // from network_client.cpp
|
extern void ClientNetworkEmergencySave(); // from network_client.cpp
|
||||||
ClientNetworkEmergencySave();
|
ClientNetworkEmergencySave();
|
||||||
|
DeleteNetworkClientWindows();
|
||||||
_switch_mode = SM_MENU;
|
_switch_mode = SM_MENU;
|
||||||
_networking = false;
|
_networking = false;
|
||||||
ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL);
|
ShowErrorMessage(STR_NETWORK_ERROR_LOSTCONNECTION, INVALID_STRING_ID, WL_CRITICAL);
|
||||||
|
@@ -522,7 +522,7 @@ static const NWidgetPart _nested_chat_window_widgets[] = {
|
|||||||
static WindowDesc _chat_window_desc(
|
static WindowDesc _chat_window_desc(
|
||||||
WDP_MANUAL, nullptr, 0, 0,
|
WDP_MANUAL, nullptr, 0, 0,
|
||||||
WC_SEND_NETWORK_MSG, WC_NONE,
|
WC_SEND_NETWORK_MSG, WC_NONE,
|
||||||
0,
|
WDF_NETWORK,
|
||||||
_nested_chat_window_widgets, lengthof(_nested_chat_window_widgets)
|
_nested_chat_window_widgets, lengthof(_nested_chat_window_widgets)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -257,6 +257,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
|
|||||||
ClientNetworkEmergencySave();
|
ClientNetworkEmergencySave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeleteNetworkClientWindows();
|
||||||
_switch_mode = SM_MENU;
|
_switch_mode = SM_MENU;
|
||||||
_networking = false;
|
_networking = false;
|
||||||
}
|
}
|
||||||
|
@@ -1016,7 +1016,7 @@ static const NWidgetPart _nested_network_game_widgets[] = {
|
|||||||
static WindowDesc _network_game_window_desc(
|
static WindowDesc _network_game_window_desc(
|
||||||
WDP_CENTER, "list_servers", 1000, 730,
|
WDP_CENTER, "list_servers", 1000, 730,
|
||||||
WC_NETWORK_WINDOW, WC_NONE,
|
WC_NETWORK_WINDOW, WC_NONE,
|
||||||
0,
|
WDF_NETWORK,
|
||||||
_nested_network_game_widgets, lengthof(_nested_network_game_widgets)
|
_nested_network_game_widgets, lengthof(_nested_network_game_widgets)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1289,7 +1289,7 @@ static const NWidgetPart _nested_network_start_server_window_widgets[] = {
|
|||||||
static WindowDesc _network_start_server_window_desc(
|
static WindowDesc _network_start_server_window_desc(
|
||||||
WDP_CENTER, nullptr, 0, 0,
|
WDP_CENTER, nullptr, 0, 0,
|
||||||
WC_NETWORK_WINDOW, WC_NONE,
|
WC_NETWORK_WINDOW, WC_NONE,
|
||||||
0,
|
WDF_NETWORK,
|
||||||
_nested_network_start_server_window_widgets, lengthof(_nested_network_start_server_window_widgets)
|
_nested_network_start_server_window_widgets, lengthof(_nested_network_start_server_window_widgets)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1366,7 +1366,7 @@ static const NWidgetPart _nested_client_list_widgets[] = {
|
|||||||
static WindowDesc _client_list_desc(
|
static WindowDesc _client_list_desc(
|
||||||
WDP_AUTO, "list_clients", 220, 300,
|
WDP_AUTO, "list_clients", 220, 300,
|
||||||
WC_CLIENT_LIST, WC_NONE,
|
WC_CLIENT_LIST, WC_NONE,
|
||||||
0,
|
WDF_NETWORK,
|
||||||
_nested_client_list_widgets, lengthof(_nested_client_list_widgets)
|
_nested_client_list_widgets, lengthof(_nested_client_list_widgets)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2259,7 +2259,7 @@ static const NWidgetPart _nested_network_join_status_window_widgets[] = {
|
|||||||
static WindowDesc _network_join_status_window_desc(
|
static WindowDesc _network_join_status_window_desc(
|
||||||
WDP_CENTER, nullptr, 0, 0,
|
WDP_CENTER, nullptr, 0, 0,
|
||||||
WC_NETWORK_STATUS_WINDOW, WC_NONE,
|
WC_NETWORK_STATUS_WINDOW, WC_NONE,
|
||||||
WDF_MODAL,
|
WDF_MODAL | WDF_NETWORK,
|
||||||
_nested_network_join_status_window_widgets, lengthof(_nested_network_join_status_window_widgets)
|
_nested_network_join_status_window_widgets, lengthof(_nested_network_join_status_window_widgets)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2382,7 +2382,7 @@ static const NWidgetPart _nested_network_company_password_window_widgets[] = {
|
|||||||
static WindowDesc _network_company_password_window_desc(
|
static WindowDesc _network_company_password_window_desc(
|
||||||
WDP_AUTO, nullptr, 0, 0,
|
WDP_AUTO, nullptr, 0, 0,
|
||||||
WC_COMPANY_PASSWORD_WINDOW, WC_NONE,
|
WC_COMPANY_PASSWORD_WINDOW, WC_NONE,
|
||||||
0,
|
WDF_NETWORK,
|
||||||
_nested_network_company_password_window_widgets, lengthof(_nested_network_company_password_window_widgets)
|
_nested_network_company_password_window_widgets, lengthof(_nested_network_company_password_window_widgets)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2484,7 +2484,7 @@ static const NWidgetPart _nested_network_ask_relay_widgets[] = {
|
|||||||
static WindowDesc _network_ask_relay_desc(
|
static WindowDesc _network_ask_relay_desc(
|
||||||
WDP_CENTER, nullptr, 0, 0,
|
WDP_CENTER, nullptr, 0, 0,
|
||||||
WC_NETWORK_ASK_RELAY, WC_NONE,
|
WC_NETWORK_ASK_RELAY, WC_NONE,
|
||||||
WDF_MODAL,
|
WDF_MODAL | WDF_NETWORK,
|
||||||
_nested_network_ask_relay_widgets, lengthof(_nested_network_ask_relay_widgets)
|
_nested_network_ask_relay_widgets, lengthof(_nested_network_ask_relay_widgets)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -3510,6 +3510,19 @@ void DeleteConstructionWindows()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all windows that use network client functionality.
|
||||||
|
*/
|
||||||
|
void DeleteNetworkClientWindows()
|
||||||
|
{
|
||||||
|
/* Note: the container remains stable, even when deleting windows. */
|
||||||
|
for (const Window *w : Window::IterateUnordered()) {
|
||||||
|
if (w->window_desc->flags & WDF_NETWORK) {
|
||||||
|
delete w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Delete all always on-top windows to get an empty screen */
|
/** Delete all always on-top windows to get an empty screen */
|
||||||
void HideVitalWindows()
|
void HideVitalWindows()
|
||||||
{
|
{
|
||||||
|
@@ -40,6 +40,7 @@ void DeleteNonVitalWindows();
|
|||||||
void DeleteAllNonVitalWindows();
|
void DeleteAllNonVitalWindows();
|
||||||
void DeleteAllMessages();
|
void DeleteAllMessages();
|
||||||
void DeleteConstructionWindows();
|
void DeleteConstructionWindows();
|
||||||
|
void DeleteNetworkClientWindows();
|
||||||
void HideVitalWindows();
|
void HideVitalWindows();
|
||||||
void ShowVitalWindows();
|
void ShowVitalWindows();
|
||||||
|
|
||||||
|
@@ -229,6 +229,7 @@ enum WindowDefaultFlag {
|
|||||||
WDF_CONSTRUCTION = 1 << 0, ///< This window is used for construction; close it whenever changing company.
|
WDF_CONSTRUCTION = 1 << 0, ///< This window is used for construction; close it whenever changing company.
|
||||||
WDF_MODAL = 1 << 1, ///< The window is a modal child of some other window, meaning the parent is 'inactive'
|
WDF_MODAL = 1 << 1, ///< The window is a modal child of some other window, meaning the parent is 'inactive'
|
||||||
WDF_NO_FOCUS = 1 << 2, ///< This window won't get focus/make any other window lose focus when click
|
WDF_NO_FOCUS = 1 << 2, ///< This window won't get focus/make any other window lose focus when click
|
||||||
|
WDF_NETWORK = 1 << 3, ///< This window is used for network client functionality
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user