Skip to content

Commit

Permalink
wesnothd: exception safety fix
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
loonycyborg committed Oct 23, 2021
1 parent ae8d61f commit 8cbecfe
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 21 deletions.
6 changes: 4 additions & 2 deletions src/server/wesnothd/server.cpp
Expand Up @@ -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_);
Expand Down Expand Up @@ -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);
}

Expand Down
45 changes: 26 additions & 19 deletions src/server/wesnothd/server.hpp
Expand Up @@ -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);
Expand Down Expand Up @@ -118,25 +125,6 @@ class server : public server_base

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_;
Expand Down Expand Up @@ -192,6 +180,25 @@ class server : public server_base

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);
Expand Down

0 comments on commit 8cbecfe

Please sign in to comment.