diff --git a/source/glest_game/menu/menu_state_custom_game.cpp b/source/glest_game/menu/menu_state_custom_game.cpp index e0e115dd1..e5a01b8f7 100644 --- a/source/glest_game/menu/menu_state_custom_game.cpp +++ b/source/glest_game/menu/menu_state_custom_game.cpp @@ -527,7 +527,10 @@ MenuStateCustomGame::~MenuStateCustomGame() { needToRepublishToMasterserver = false; //BaseThread::shutdownAndWait(publishToMasterserverThread); - delete publishToMasterserverThread; + if(publishToMasterserverThread != NULL && + publishToMasterserverThread->shutdownAndWait() == true) { + delete publishToMasterserverThread; + } publishToMasterserverThread = NULL; publishToMasterserverThreadInDeletion = false; safeMutexPtr.ReleaseLock(); @@ -556,7 +559,10 @@ void MenuStateCustomGame::returnToParentMenu(){ bool returnToMasterServerMenu = parentMenuIsMs; //BaseThread::shutdownAndWait(publishToMasterserverThread); - delete publishToMasterserverThread; + if(publishToMasterserverThread != NULL && + publishToMasterserverThread->shutdownAndWait() == true) { + delete publishToMasterserverThread; + } publishToMasterserverThread = NULL; publishToMasterserverThreadInDeletion = false; safeMutexPtr.ReleaseLock(); @@ -605,7 +611,10 @@ void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){ MutexSafeWrapper safeMutexPtr(&publishToMasterserverThreadPtrChangeAccessor); publishToMasterserverThreadInDeletion = true; //BaseThread::shutdownAndWait(publishToMasterserverThread); - delete publishToMasterserverThread; + if(publishToMasterserverThread != NULL && + publishToMasterserverThread->shutdownAndWait() == true) { + delete publishToMasterserverThread; + } publishToMasterserverThread = NULL; publishToMasterserverThreadInDeletion = false; safeMutexPtr.ReleaseLock(); @@ -1115,7 +1124,10 @@ void MenuStateCustomGame::PlayNow() { MutexSafeWrapper safeMutexPtr(&publishToMasterserverThreadPtrChangeAccessor); publishToMasterserverThreadInDeletion = true; //BaseThread::shutdownAndWait(publishToMasterserverThread); - delete publishToMasterserverThread; + if(publishToMasterserverThread != NULL && + publishToMasterserverThread->shutdownAndWait() == true) { + delete publishToMasterserverThread; + } publishToMasterserverThread = NULL; publishToMasterserverThreadInDeletion = false; safeMutexPtr.ReleaseLock(); @@ -1837,8 +1849,16 @@ void MenuStateCustomGame::publishToMasterserver() void MenuStateCustomGame::simpleTask() { - //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); + if(publishToMasterserverThreadInDeletion == true) { + return; + } + if( publishToMasterserverThread == NULL || + publishToMasterserverThread->getQuitStatus() == true) { + return; + } + + //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); MutexSafeWrapper safeMutex(&masterServerThreadAccessor); bool republish = (needToRepublishToMasterserver == true && publishToServerInfo.size() != 0); needToRepublishToMasterserver = false; diff --git a/source/glest_game/menu/menu_state_masterserver.cpp b/source/glest_game/menu/menu_state_masterserver.cpp index b4dfd31f9..fa5d0d2cd 100644 --- a/source/glest_game/menu/menu_state_masterserver.cpp +++ b/source/glest_game/menu/menu_state_masterserver.cpp @@ -332,7 +332,6 @@ MenuStateMasterserver::MenuStateMasterserver(Program *program, MainMenu *mainMen NetworkManager::getInstance().end(); NetworkManager::getInstance().init(nrClient); - //updateServerInfo(); // write hint to console: Config &configKeys = Config::getInstance(std::pair(cfgMainKeys,cfgUserKeys)); @@ -365,7 +364,10 @@ MenuStateMasterserver::~MenuStateMasterserver() { //BaseThread::shutdownAndWait(updateFromMasterserverThread); masterServerThreadInDeletion = true; - delete updateFromMasterserverThread; + if(updateFromMasterserverThread != NULL && + updateFromMasterserverThread->shutdownAndWait() == true) { + delete updateFromMasterserverThread; + } updateFromMasterserverThread = NULL; masterServerThreadInDeletion = false; safeMutexPtr.ReleaseLock(); @@ -411,7 +413,6 @@ void MenuStateMasterserver::mouseClick(int x, int y, MouseButton mouseButton){ MutexSafeWrapper safeMutex(&masterServerThreadAccessor); soundRenderer.playFx(coreData.getClickSoundB()); - //updateServerInfo(); needUpdateFromServer = true; SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -425,7 +426,10 @@ void MenuStateMasterserver::mouseClick(int x, int y, MouseButton mouseButton){ //BaseThread::shutdownAndWait(updateFromMasterserverThread); MutexSafeWrapper safeMutexPtr(&masterServerThreadPtrChangeAccessor); masterServerThreadInDeletion = true; - delete updateFromMasterserverThread; + if(updateFromMasterserverThread != NULL && + updateFromMasterserverThread->shutdownAndWait() == true) { + delete updateFromMasterserverThread; + } updateFromMasterserverThread = NULL; masterServerThreadInDeletion = false; safeMutexPtr.ReleaseLock(); @@ -451,7 +455,10 @@ void MenuStateMasterserver::mouseClick(int x, int y, MouseButton mouseButton){ //BaseThread::shutdownAndWait(updateFromMasterserverThread); MutexSafeWrapper safeMutexPtr(&masterServerThreadPtrChangeAccessor); masterServerThreadInDeletion = true; - delete updateFromMasterserverThread; + if(updateFromMasterserverThread != NULL && + updateFromMasterserverThread->shutdownAndWait() == true) { + delete updateFromMasterserverThread; + } updateFromMasterserverThread = NULL; masterServerThreadInDeletion = false; safeMutexPtr.ReleaseLock(); @@ -481,8 +488,10 @@ void MenuStateMasterserver::mouseClick(int x, int y, MouseButton mouseButton){ MutexSafeWrapper safeMutexPtr(&masterServerThreadPtrChangeAccessor); masterServerThreadInDeletion = true; - BaseThread::shutdownAndWait(updateFromMasterserverThread); - delete updateFromMasterserverThread; + if(updateFromMasterserverThread != NULL && + updateFromMasterserverThread->shutdownAndWait() == true) { + delete updateFromMasterserverThread; + } updateFromMasterserverThread = NULL; masterServerThreadInDeletion = false; safeMutexPtr.ReleaseLock(); @@ -597,6 +606,10 @@ void MenuStateMasterserver::update(){ } void MenuStateMasterserver::simpleTask() { + if(masterServerThreadInDeletion == true) { + return; + } + if( updateFromMasterserverThread == NULL || updateFromMasterserverThread->getQuitStatus() == true) { return; diff --git a/source/glest_game/network/network_message.cpp b/source/glest_game/network/network_message.cpp index 1ae7939dd..864ad5d8c 100644 --- a/source/glest_game/network/network_message.cpp +++ b/source/glest_game/network/network_message.cpp @@ -387,6 +387,8 @@ void NetworkMessageCommandList::send(Socket* socket) const{ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] index = %d, sent networkCommand [%s]\n", __FILE__,__FUNCTION__,__LINE__,idx, cmd.toString().c_str()); } + + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] END of loop, nmtCommandList, frameCount = %d, data.header.commandCount = %d, data.header.messageType = %d\n",__FILE__,__FUNCTION__,__LINE__,data.header.frameCount,data.header.commandCount,data.header.messageType); } } } diff --git a/source/shared_lib/include/platform/common/base_thread.h b/source/shared_lib/include/platform/common/base_thread.h index 50aec40a0..36a7a26d7 100644 --- a/source/shared_lib/include/platform/common/base_thread.h +++ b/source/shared_lib/include/platform/common/base_thread.h @@ -51,8 +51,9 @@ public: virtual bool getHasBeginExecution(); virtual void setHasBeginExecution(bool value); - static void shutdownAndWait(BaseThread *ppThread); - virtual void shutdownAndWait(); + static bool shutdownAndWait(BaseThread *ppThread); + virtual bool shutdownAndWait(); + virtual bool canShutdown() { return true; } void setUniqueID(string value) { uniqueID = value; } string getUniqueID() { return uniqueID; } diff --git a/source/shared_lib/include/platform/common/simple_threads.h b/source/shared_lib/include/platform/common/simple_threads.h index 7d69b9888..241f6c89b 100644 --- a/source/shared_lib/include/platform/common/simple_threads.h +++ b/source/shared_lib/include/platform/common/simple_threads.h @@ -61,6 +61,9 @@ protected: bool taskSignalled; bool needTaskSignal; + Mutex mutexExecutingTask; + bool executingTask; + public: SimpleTaskThread(); SimpleTaskThread(SimpleTaskCallbackInterface *simpleTaskInterface, @@ -68,8 +71,12 @@ public: unsigned int millisecsBetweenExecutions=0, bool needTaskSignal = false); virtual void execute(); + virtual bool canShutdown(); + void setTaskSignalled(bool value); bool getTaskSignalled(); + void setExecutingTask(bool value); + bool getExecutingTask(); }; }}//end namespace diff --git a/source/shared_lib/sources/platform/common/base_thread.cpp b/source/shared_lib/sources/platform/common/base_thread.cpp index f9883e8e5..ff4183447 100644 --- a/source/shared_lib/sources/platform/common/base_thread.cpp +++ b/source/shared_lib/sources/platform/common/base_thread.cpp @@ -33,8 +33,8 @@ BaseThread::BaseThread() : Thread() { BaseThread::~BaseThread() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); - shutdownAndWait(); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); + bool ret = shutdownAndWait(); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret); } void BaseThread::signalQuit() { @@ -117,32 +117,50 @@ void BaseThread::setRunningStatus(bool value) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); } -void BaseThread::shutdownAndWait(BaseThread *pThread) { +bool BaseThread::shutdownAndWait(BaseThread *pThread) { + bool ret = false; + if(pThread != NULL) { + ret = pThread->shutdownAndWait(); + } + + return ret; +} + +bool BaseThread::shutdownAndWait() { + bool ret = true; + BaseThread *pThread = this; string uniqueID = (pThread != NULL ? pThread->getUniqueID() : "?"); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); - if(pThread != NULL && pThread->getRunningStatus() == true) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); + if(pThread != NULL) { + if(pThread->getRunningStatus() == true) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); - pThread->signalQuit(); - //sleep(0); + pThread->signalQuit(); + //sleep(0); + ret = false; - for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 7; ) { - if(pThread->getRunningStatus() == false) { - break; + int maxWaitSeconds = 7; + if(pThread->canShutdown() == false) { + maxWaitSeconds = 3; } - sleep(1); - //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= maxWaitSeconds; ) { + if(pThread->getRunningStatus() == false) { + ret = true; + break; + } + + sleep(0); + //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + } + //sleep(0); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); } - //sleep(0); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); } //sleep(0); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); -} - -void BaseThread::shutdownAndWait() { - BaseThread::shutdownAndWait(this); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret); + return ret; } }}//end namespace diff --git a/source/shared_lib/sources/platform/common/simple_threads.cpp b/source/shared_lib/sources/platform/common/simple_threads.cpp index c96d052aa..076fe2de5 100644 --- a/source/shared_lib/sources/platform/common/simple_threads.cpp +++ b/source/shared_lib/sources/platform/common/simple_threads.cpp @@ -83,6 +83,11 @@ SimpleTaskThread::SimpleTaskThread( SimpleTaskCallbackInterface *simpleTaskInter this->millisecsBetweenExecutions = millisecsBetweenExecutions; this->needTaskSignal = needTaskSignal; setTaskSignalled(false); + setExecutingTask(false); +} + +bool SimpleTaskThread::canShutdown() { + return (getExecutingTask() == false); } void SimpleTaskThread::execute() { @@ -97,7 +102,6 @@ void SimpleTaskThread::execute() { unsigned int idx = 0; for(;this->simpleTaskInterface != NULL;) { - bool runTask = true; if(needTaskSignal == true) { runTask = getTaskSignalled(); @@ -113,7 +117,15 @@ void SimpleTaskThread::execute() { else if(runTask == true) { //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->getUniqueID().c_str()); if(getQuitStatus() == false) { - this->simpleTaskInterface->simpleTask(); + try { + setExecutingTask(true); + this->simpleTaskInterface->simpleTask(); + setExecutingTask(false); + } + catch(const exception &ex) { + setExecutingTask(false); + throw runtime_error(ex.what()); + } } //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,this->getUniqueID().c_str()); } @@ -173,4 +185,19 @@ bool SimpleTaskThread::getTaskSignalled() { return retval; } +void SimpleTaskThread::setExecutingTask(bool value) { + MutexSafeWrapper safeMutex(&mutexExecutingTask); + executingTask = value; + safeMutex.ReleaseLock(); +} + +bool SimpleTaskThread::getExecutingTask() { + bool retval = false; + MutexSafeWrapper safeMutex(&mutexExecutingTask); + retval = executingTask; + safeMutex.ReleaseLock(); + + return retval; +} + }}//end namespace diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index 1f11c1701..14c285b19 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -1017,6 +1017,7 @@ int Socket::send(const void *data, int dataSize) { attemptCount++; SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d\n",__FILE__,__FUNCTION__,__LINE__,attemptCount); + sleep(0); //if(Socket::isWritable(true) == true) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d, sock = %d, dataSize = %d, data = %p\n",__FILE__,__FUNCTION__,__LINE__,attemptCount,sock,dataSize,data); #ifdef __APPLE__ @@ -1044,6 +1045,7 @@ int Socket::send(const void *data, int dataSize) { attemptCount++; SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d, totalBytesSent = %d\n",__FILE__,__FUNCTION__,__LINE__,attemptCount,totalBytesSent); + sleep(0); //if(bytesSent > 0 || Socket::isWritable(true) == true) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] attemptCount = %d, sock = %d, dataSize = %d, data = %p\n",__FILE__,__FUNCTION__,__LINE__,attemptCount,sock,dataSize,data); @@ -1101,7 +1103,8 @@ int Socket::receive(void *data, int dataSize) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 EAGAIN during receive, trying again...\n",__FILE__,__FUNCTION__,__LINE__); time_t tStartTimer = time(NULL); - while((bytesReceived < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) { + while((bytesReceived < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) && + (difftime(time(NULL),tStartTimer) <= 5)) { if(Socket::isReadable() == true) { MutexSafeWrapper safeMutex(&dataSynchAccessor); bytesReceived = recv(sock, reinterpret_cast(data), dataSize, 0); @@ -1137,7 +1140,8 @@ int Socket::peek(void *data, int dataSize){ SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] #1 EAGAIN during peek, trying again...\n",__FILE__,__FUNCTION__,__LINE__); time_t tStartTimer = time(NULL); - while((err < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) && (difftime(time(NULL),tStartTimer) <= 5)) { + while((err < 0 && getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) && + (difftime(time(NULL),tStartTimer) <= 5)) { if(Socket::isReadable() == true) { //MutexSafeWrapper safeMutex(&dataSynchAccessor); err = recv(sock, reinterpret_cast(data), dataSize, MSG_PEEK); @@ -1220,35 +1224,45 @@ bool Socket::isWritable(bool waitOnDelayedResponse) { FD_ZERO(&set); FD_SET(sock, &set); + time_t maxElapsedCheck = time(NULL); + const int MAX_CHECK_WAIT_SECONDS = 5; + bool result = false; do { + if(difftime(time(NULL),maxElapsedCheck) >= MAX_CHECK_WAIT_SECONDS) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] max timeout waited during writable check\n",__FILE__,__FUNCTION__,__LINE__); + break; + } + int i = 0; { //MutexSafeWrapper safeMutex(&dataSynchAccessor); i = select((int)sock + 1, NULL, &set, NULL, &tv); } if(i < 0 ) { - if(difftime(time(NULL),lastDebugEvent) >= 1) { + //if(difftime(time(NULL),lastDebugEvent) >= 1) { lastDebugEvent = time(NULL); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s] error while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,i,getLastSocketErrorFormattedText().c_str()); - } + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] error while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,i,getLastSocketErrorFormattedText().c_str()); + //} waitOnDelayedResponse = false; //throwException("Error selecting socket"); } else if(i == 0) { - if(difftime(time(NULL),lastDebugEvent) >= 1) { + //if(difftime(time(NULL),lastDebugEvent) >= 1) { lastDebugEvent = time(NULL); - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s] TIMEOUT while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,i,getLastSocketErrorFormattedText().c_str()); - } + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s Line: %d] TIMEOUT while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,__LINE__,i,getLastSocketErrorFormattedText().c_str()); + //} if(waitOnDelayedResponse == false) { result = true; + break; } } else { result = true; + break; } } while(waitOnDelayedResponse == true && result == false);