1
0
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:
Arseniy Shestakov 2017-06-04 11:59:26 +03:00
parent 3f7cb9f893
commit a2284c3209
6 changed files with 39 additions and 30 deletions

View File

@ -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>

View File

@ -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
{

View File

@ -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

View File

@ -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)

View File

@ -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)
{

View File

@ -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 (...)
{