wesnothd: exception safety fix

This fixes crash in response to server_shutdown exception getting
thrown, as well as any other exception, that happens if there are any
players logged on.
This commit is contained in:
loonycyborg 2021-10-23 22:45:58 +03:00
parent bfa16ee0c7
commit ab97a37394
No known key found for this signature in database
GPG key ID: 6E8233FAB8F26D61
2 changed files with 30 additions and 21 deletions

View file

@ -1069,7 +1069,9 @@ template<class SocketPtr> void server::handle_player(boost::asio::yield_context
assert(inserted);
BOOST_SCOPE_EXIT_ALL(this, &player) {
remove_player(player);
if(!destructed) {
remove_player(player);
}
};
async_send_doc_queued(socket, games_and_users_list_);
@ -1368,7 +1370,7 @@ void server::cleanup_game(game* game_ptr)
// Send a diff of the gamelist with the game deleted to players in the lobby
simple_wml::document diff;
if(make_delete_diff(*gamelist, "gamelist", "game", game_ptr->description(), diff)) {
if(!destructed && make_delete_diff(*gamelist, "gamelist", "game", game_ptr->description(), diff)) {
send_to_lobby(diff);
}

View file

@ -37,6 +37,13 @@ class server : public server_base
public:
server(int port, bool keep_alive, const std::string& config_file, std::size_t, std::size_t);
// We keep this flag for coroutines. Since they get their stack unwinding done after player_connections_
// is already destroyed they need to know to avoid calling remove_player() on invalid iterators.
bool destructed = false;
~server() {
destructed = true;
}
private:
void handle_new_client(socket_ptr socket);
void handle_new_client(tls_socket_ptr socket);
@ -118,25 +125,6 @@ private:
std::mt19937 die_;
player_connections player_connections_;
std::deque<std::shared_ptr<game>> games() const
{
std::deque<std::shared_ptr<game>> result;
for(const auto& iter : player_connections_.get<game_t>()) {
if(result.empty() || iter.get_game() != result.back()) {
result.push_back(iter.get_game());
}
}
if(!result.empty() && result.front() == nullptr) {
result.pop_front();
}
return result;
}
#ifndef _WIN32
/** server socket/fifo. */
std::string input_path_;
@ -192,6 +180,25 @@ private:
metrics metrics_;
player_connections player_connections_;
std::deque<std::shared_ptr<game>> games() const
{
std::deque<std::shared_ptr<game>> result;
for(const auto& iter : player_connections_.get<game_t>()) {
if(result.empty() || iter.get_game() != result.back()) {
result.push_back(iter.get_game());
}
}
if(!result.empty() && result.front() == nullptr) {
result.pop_front();
}
return result;
}
boost::asio::steady_timer dump_stats_timer_;
void start_dump_stats();
void dump_stats(const boost::system::error_code& ec);