From b109b266648899f93daf2f46b8336bfb6f4bad0d Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Mon, 30 Dec 2013 21:23:49 -0800 Subject: [PATCH] - attempt to add crude thread state tracking in thread class and force thread to die if it appears to be stuck (and output to console) --- .../shared_lib/include/platform/sdl/thread.h | 13 ++++ .../sources/platform/sdl/thread.cpp | 59 +++++++++++++++++-- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/source/shared_lib/include/platform/sdl/thread.h b/source/shared_lib/include/platform/sdl/thread.h index 8c439608..744c2596 100644 --- a/source/shared_lib/include/platform/sdl/thread.h +++ b/source/shared_lib/include/platform/sdl/thread.h @@ -46,6 +46,17 @@ namespace Shared { namespace Platform { class Mutex; //class uint32; +enum ThreadState { + thrsNew, + thrsStarting, + thrsExecuteStart, + thrsExecuting, + thrsExecuted, + thrsExecuteAutoClean, + thrsExecuteComplete + +}; + class Thread { public: enum Priority { @@ -60,6 +71,7 @@ private: SDL_Thread* thread; //std::auto_ptr mutexthreadAccessor; Mutex *mutexthreadAccessor; + ThreadState currentState; bool threadObjectValid(); bool deleteAfterExecute; @@ -71,6 +83,7 @@ protected: void addThreadToList(); void removeThreadFromList(); void queueAutoCleanThread(); + bool isThreadExecuteCompleteStatus(); public: Thread(); diff --git a/source/shared_lib/sources/platform/sdl/thread.cpp b/source/shared_lib/sources/platform/sdl/thread.cpp index f3295391..f82ed1ed 100644 --- a/source/shared_lib/sources/platform/sdl/thread.cpp +++ b/source/shared_lib/sources/platform/sdl/thread.cpp @@ -128,7 +128,9 @@ public: // ===================================== // Threads // ===================================== -Thread::Thread() : thread(NULL), mutexthreadAccessor(new Mutex(CODE_AT_LINE)), deleteAfterExecute(false) { +Thread::Thread() : thread(NULL), + mutexthreadAccessor(new Mutex(CODE_AT_LINE)), + deleteAfterExecute(false), currentState(thrsNew) { addThreadToList(); } @@ -184,15 +186,43 @@ void Thread::shutdownThreads() { } } +bool Thread::isThreadExecuteCompleteStatus() { + MutexSafeWrapper safeMutex(mutexthreadAccessor); + return (currentState == thrsExecuteComplete); +} Thread::~Thread() { if(Thread::getEnableVerboseMode()) printf("In ~Thread Line: %d [%p] thread = %p\n",__LINE__,this,thread); MutexSafeWrapper safeMutex(mutexthreadAccessor); if(thread != NULL) { - SDL_WaitThread(thread, NULL); + + safeMutex.ReleaseLock(); + + if(isThreadExecuteCompleteStatus() == false) { + printf("**WARNING** thread destructor delayed, trying to exit...\n"); + + time_t elapsed = time(NULL); + for(;difftime((long int)time(NULL),elapsed) <= 5;) { + sleep(0); + + if(isThreadExecuteCompleteStatus() == true) { + break; + } + } + } + + if(isThreadExecuteCompleteStatus() == false) { + printf("**WARNING** thread destructor will KILL thread [%p]...\n",thread); + SDL_KillThread(thread); + } + else { + SDL_WaitThread(thread, NULL); + } thread = NULL; } - safeMutex.ReleaseLock(); + else { + safeMutex.ReleaseLock(); + } if(Thread::getEnableVerboseMode()) printf("In ~Thread Line: %d [%p] thread = %p\n",__LINE__,this,thread); @@ -213,12 +243,12 @@ std::vector Thread::getThreadList() { void Thread::start() { MutexSafeWrapper safeMutex(mutexthreadAccessor); + currentState = thrsStarting; BaseThread *base_thread = dynamic_cast(this); if(base_thread) base_thread->setStarted(true); thread = SDL_CreateThread(beginExecution, this); - //assert(thread != NULL); if(thread == NULL) { if(base_thread) base_thread->setStarted(false); @@ -241,28 +271,47 @@ void Thread::setPriority(Thread::Priority threadPriority) { int Thread::beginExecution(void* data) { Thread* thread = static_cast (data); - assert(thread != NULL); if(thread == NULL) { char szBuf[8096]=""; snprintf(szBuf,8095,"In [%s::%s Line: %d] thread == NULL",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); + printf("%s",szBuf); + throw megaglest_runtime_error(szBuf); } + MutexSafeWrapper safeMutex(thread->mutexthreadAccessor); + thread->currentState = thrsExecuteStart; + safeMutex.ReleaseLock(true); + BaseThread *base_thread = dynamic_cast(thread); //ThreadGarbageCollector *garbage_collector = dynamic_cast(thread); if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d thread = %p base_thread = %p [%s]\n",__LINE__,thread,base_thread,(base_thread != NULL ? base_thread->getUniqueID().c_str() : "n/a")); if(thread->threadObjectValid() == true) { + safeMutex.Lock(); + thread->currentState = thrsExecuting; + safeMutex.ReleaseLock(true); + thread->execute(); + + safeMutex.Lock(); + thread->currentState = thrsExecuted; + safeMutex.ReleaseLock(true); } if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d thread = %p base_thread = %p [%s]\n",__LINE__,thread,base_thread,(base_thread != NULL ? base_thread->getUniqueID().c_str() : "n/a")); if(thread->threadObjectValid() == true) { + safeMutex.Lock(); + thread->currentState = thrsExecuteAutoClean; + safeMutex.ReleaseLock(true); thread->queueAutoCleanThread(); } if(Thread::getEnableVerboseMode()) printf("In Thread::execute Line: %d\n",__LINE__); + safeMutex.Lock(); + thread->currentState = thrsExecuteComplete; + safeMutex.ReleaseLock(); return 0; }