From 60b58eb44c0150eef578a62f9810ca6e07d2b845 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Thu, 20 Jan 2011 07:56:02 +0000 Subject: [PATCH] - bugfix for multi-build segfault under special conditions (discovered today) --- source/glest_game/game/commander.h | 3 +- source/glest_game/world/unit_updater.cpp | 55 ++++++++++++++++++------ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/source/glest_game/game/commander.h b/source/glest_game/game/commander.h index c64b283c..a89e854c 100644 --- a/source/glest_game/game/commander.h +++ b/source/glest_game/game/commander.h @@ -101,10 +101,11 @@ public: CommandResult pushNetworkCommand(const NetworkCommand* networkCommand) const; //void giveNetworkCommandSpecial(const NetworkCommand* networkCommand) const; + Command* buildCommand(const NetworkCommand* networkCommand) const; + private: CommandResult computeResult(const CommandResultContainer &results) const; void giveNetworkCommand(NetworkCommand* networkCommand) const; - Command* buildCommand(const NetworkCommand* networkCommand) const; virtual void commanderNetworkUpdateTask(int id); }; diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index c74318f4..2285a419 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -1155,7 +1155,7 @@ void UnitUpdater::updateRepair(Unit *unit) { if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); - // Esnure we have the right unit to repair + // Ensure we have the right unit to repair if(peerUnitBuilder != NULL) { SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d] peerUnitBuilder = %p\n",__FILE__,__FUNCTION__,__LINE__,peerUnitBuilder); @@ -1195,18 +1195,49 @@ void UnitUpdater::updateRepair(Unit *unit) { if(nextToRepaired == true) { SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - CommandStateType commandStateType = unit->getCurrCommand()->getStateType(); - SwapActiveCommand(unit,peerUnitBuilder); - int oldPeerUnitId = peerUnitBuilder->getId(); - int newPeerUnitId = unit->getId(); - SwapActiveCommandState(unit,commandStateType,unit->getCurrCommand()->getCommandType(),oldPeerUnitId,newPeerUnitId); + Command *peerCommand = peerUnitBuilder->getCurrCommand(); + const RepairCommandType *rct = dynamic_cast(peerCommand->getCommandType()); + // If the peer is also scheduled to do a repair we CANNOT swap their commands or + // it will result in a stack overflow as each swaps the others repair command. + // We must convert this unit's repair into a build right now! + if(rct != NULL) { + SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - // Give the swapped unit a fresh chance to help build in case they - // were or are about to be blocked - peerUnitBuilder->getPath()->clear(); - peerUnitBuilder->setRetryCurrCommandCount(1); - updateUnitCommand(unit); - //updateUnitCommand(peerUnitBuilder); + const CommandType *ctbuild = unit->getType()->getFirstCtOfClass(ccBuild); + NetworkCommand networkCommand(this->world,nctGiveCommand, unit->getId(), ctbuild->getId(), command->getPos(), + command->getUnitType()->getId(), -1, CardinalDir::NORTH, true, command->getStateType(), + command->getStateValue()); + + SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + Command* command= this->game->getCommander()->buildCommand(&networkCommand); + CommandResult cr= unit->checkCommand(command); + if(cr == crSuccess) { + SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + unit->replaceCurrCommand(command); + } + else { + SystemFlags::OutputDebug(SystemFlags::debugUnitCommands,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + delete command; + + unit->setCurrSkill(scStop); + unit->finishCommand(); + } + } + else { + CommandStateType commandStateType = unit->getCurrCommand()->getStateType(); + SwapActiveCommand(unit,peerUnitBuilder); + int oldPeerUnitId = peerUnitBuilder->getId(); + int newPeerUnitId = unit->getId(); + SwapActiveCommandState(unit,commandStateType,unit->getCurrCommand()->getCommandType(),oldPeerUnitId,newPeerUnitId); + + // Give the swapped unit a fresh chance to help build in case they + // were or are about to be blocked + peerUnitBuilder->getPath()->clear(); + peerUnitBuilder->setRetryCurrCommandCount(1); + updateUnitCommand(unit); + //updateUnitCommand(peerUnitBuilder); + } return; } }