mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Automated testing: graceful shutdown for when game is ended
Before when CloseServer / LeaveGame applied there was no thread sync on server. Now server use std::atomic bool for synchronization and graceful shutdown.
This commit is contained in:
parent
3f7cb9f893
commit
a2284c3209
1
Global.h
1
Global.h
@ -143,6 +143,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
|
||||
//The only available version is 3, as of Boost 1.50
|
||||
#include <boost/version.hpp>
|
||||
|
@ -517,9 +517,10 @@ int main(int argc, char** argv)
|
||||
bfs::path fileToStartFrom; //none by default
|
||||
if(vm.count("start"))
|
||||
fileToStartFrom = vm["start"].as<bfs::path>();
|
||||
std::string testmap;
|
||||
if(vm.count("testmap"))
|
||||
testmap = vm["testmap"].as<std::string>();
|
||||
{
|
||||
session["testmap"].String() = vm["testmap"].as<std::string>();
|
||||
}
|
||||
|
||||
session["spectate"].Bool() = vm.count("spectate");
|
||||
if(session["spectate"].Bool())
|
||||
@ -532,9 +533,9 @@ int main(int argc, char** argv)
|
||||
if(vm.count("spectate-battle-speed"))
|
||||
session["spectate-battle-speed"].Float() = vm["spectate-battle-speed"].as<int>();
|
||||
}
|
||||
if(!testmap.empty())
|
||||
if(!session["testmap"].isNull())
|
||||
{
|
||||
startTestMap(testmap);
|
||||
startTestMap(session["testmap"].String());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -714,19 +714,22 @@ void CClient::stopConnection()
|
||||
{
|
||||
terminate = true;
|
||||
|
||||
if (serv && serv->isHost()) //request closing connection
|
||||
if(serv)
|
||||
{
|
||||
logNetwork->infoStream() << "Connection has been requested to be closed.";
|
||||
boost::unique_lock<boost::mutex>(*serv->wmx);
|
||||
CloseServer close_server;
|
||||
sendRequest(&close_server, PlayerColor::NEUTRAL);
|
||||
logNetwork->infoStream() << "Sent closing signal to the server";
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveGame leave_Game;
|
||||
sendRequest(&leave_Game, PlayerColor::NEUTRAL);
|
||||
logNetwork->infoStream() << "Sent leaving signal to the server";
|
||||
if(serv->isHost()) //request closing connection
|
||||
{
|
||||
logNetwork->infoStream() << "Connection has been requested to be closed.";
|
||||
CloseServer close_server;
|
||||
sendRequest(&close_server, PlayerColor::NEUTRAL);
|
||||
logNetwork->infoStream() << "Sent closing signal to the server";
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveGame leave_Game;
|
||||
sendRequest(&leave_Game, PlayerColor::NEUTRAL);
|
||||
logNetwork->infoStream() << "Sent leaving signal to the server";
|
||||
}
|
||||
}
|
||||
|
||||
if(connectionHandler)//end connection handler
|
||||
|
@ -302,6 +302,10 @@ void ChangeObjPos::applyCl(CClient *cl)
|
||||
void PlayerEndsGame::applyCl(CClient *cl)
|
||||
{
|
||||
CALL_IN_ALL_INTERFACES(gameOver, player, victoryLossCheckResult);
|
||||
|
||||
// In auto testing mode we always close client if red player won or lose
|
||||
if(!settings["session"]["testmap"].isNull() && player == PlayerColor(0))
|
||||
handleQuit(settings["session"]["spectate"].Bool()); // if spectator is active ask to close client or not
|
||||
}
|
||||
|
||||
void RemoveBonus::applyCl(CClient *cl)
|
||||
|
@ -48,7 +48,7 @@
|
||||
#ifndef _MSC_VER
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#endif
|
||||
extern bool end2;
|
||||
extern std::atomic<bool> serverShuttingDown;
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
@ -1033,12 +1033,13 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
|
||||
|
||||
auto handleDisconnection = [&](const std::exception & e)
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(*c.wmx);
|
||||
assert(!c.connected); //make sure that connection has been marked as broken
|
||||
logGlobal->error(e.what());
|
||||
conns -= &c;
|
||||
for(auto playerConn : connections)
|
||||
{
|
||||
if(playerConn.second == &c)
|
||||
if(!serverShuttingDown && playerConn.second == &c)
|
||||
{
|
||||
PlayerCheated pc;
|
||||
pc.player = playerConn.first;
|
||||
@ -1128,7 +1129,7 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
end2 = true;
|
||||
serverShuttingDown = true;
|
||||
handleException();
|
||||
throw;
|
||||
}
|
||||
@ -1902,7 +1903,7 @@ void CGameHandler::run(bool resume)
|
||||
if (gs->scenarioOps->mode == StartInfo::DUEL)
|
||||
{
|
||||
runBattle();
|
||||
end2 = true;
|
||||
serverShuttingDown = true;
|
||||
|
||||
|
||||
while(conns.size() && (*conns.begin())->isOpen())
|
||||
@ -1913,7 +1914,7 @@ void CGameHandler::run(bool resume)
|
||||
|
||||
auto playerTurnOrder = generatePlayerTurnOrder();
|
||||
|
||||
while(!end2)
|
||||
while(!serverShuttingDown)
|
||||
{
|
||||
if (!resume) newTurn();
|
||||
|
||||
@ -1954,7 +1955,7 @@ void CGameHandler::run(bool resume)
|
||||
|
||||
//wait till turn is done
|
||||
boost::unique_lock<boost::mutex> lock(states.mx);
|
||||
while (states.players.at(playerColor).makingTurn && !end2)
|
||||
while(states.players.at(playerColor).makingTurn && !serverShuttingDown)
|
||||
{
|
||||
static time_duration p = milliseconds(100);
|
||||
states.cv.timed_wait(lock, p);
|
||||
@ -1970,7 +1971,7 @@ void CGameHandler::run(bool resume)
|
||||
activePlayer = true;
|
||||
}
|
||||
if (!activePlayer)
|
||||
end2 = true;
|
||||
serverShuttingDown = true;
|
||||
}
|
||||
while(conns.size() && (*conns.begin())->isOpen())
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(5)); //give time client to close socket
|
||||
@ -2734,7 +2735,7 @@ void CGameHandler::close()
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
end2 = true;
|
||||
serverShuttingDown = true;
|
||||
|
||||
for (auto & elem : conns)
|
||||
{
|
||||
@ -2745,7 +2746,6 @@ void CGameHandler::close()
|
||||
elem->close();
|
||||
elem->connected = false;
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void CGameHandler::playerLeftGame(int cid)
|
||||
@ -5103,7 +5103,7 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
|
||||
|
||||
if (p->human)
|
||||
{
|
||||
end2 = true;
|
||||
serverShuttingDown = true;
|
||||
|
||||
if (gs->scenarioOps->campState)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + NAME_AFFIX
|
||||
#ifndef VCMI_ANDROID
|
||||
namespace intpr = boost::interprocess;
|
||||
#endif
|
||||
bool end2 = false;
|
||||
std::atomic<bool> serverShuttingDown(false);
|
||||
|
||||
boost::program_options::variables_map cmdLineOptions;
|
||||
|
||||
@ -107,7 +107,7 @@ void CPregameServer::handleConnection(CConnection *cpc)
|
||||
}
|
||||
else if(quitting) // Server must be stopped if host is leaving from lobby to avoid crash
|
||||
{
|
||||
end2 = true;
|
||||
serverShuttingDown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -477,7 +477,7 @@ void CVCMIServer::start()
|
||||
std::string name = NAME;
|
||||
firstConnection = new CConnection(s, name.append(" STATE_WAITING"));
|
||||
logNetwork->info("Got connection!");
|
||||
while(!end2)
|
||||
while(!serverShuttingDown)
|
||||
{
|
||||
ui8 mode;
|
||||
*firstConnection >> mode;
|
||||
@ -649,7 +649,7 @@ int main(int argc, char** argv)
|
||||
|
||||
try
|
||||
{
|
||||
while (!end2)
|
||||
while(!serverShuttingDown)
|
||||
{
|
||||
server.start();
|
||||
}
|
||||
@ -658,7 +658,7 @@ int main(int argc, char** argv)
|
||||
catch (boost::system::system_error &e) //for boost errors just log, not crash - probably client shut down connection
|
||||
{
|
||||
logNetwork->error(e.what());
|
||||
end2 = true;
|
||||
serverShuttingDown = true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user