- bugfix for unit selection segfault on game exit

- added thread hardening to try to ensure we never try to delete a thread more than once.
This commit is contained in:
Mark Vejvoda 2012-04-12 20:43:19 +00:00
parent 76c3fa1949
commit 9aca26a0f0
5 changed files with 73 additions and 11 deletions

View File

@ -1676,14 +1676,29 @@ void Game::renderWorker() {
// ==================== tick ====================
void Game::removeUnitFromSelection(const Unit *unit) {
Selection *selection= getGuiPtr()->getSelectionPtr();
for(int i=0; i < selection->getCount(); ++i) {
const Unit *currentUnit = selection->getUnit(i);
if(currentUnit == unit) {
selection->unSelect(i);
break;
try {
Selection *selection= gui.getSelectionPtr();
for(int i=0; i < selection->getCount(); ++i) {
const Unit *currentUnit = selection->getUnit(i);
if(currentUnit == unit) {
selection->unSelect(i);
break;
}
}
}
catch(const exception &ex) {
char szBuf[4096]="";
sprintf(szBuf,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
SystemFlags::OutputDebug(SystemFlags::debugError,szBuf);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,szBuf);
if(errorMessageBox.getEnabled() == false) {
ErrorDisplayMessage(ex.what(),true);
}
//abort();
}
}
void Game::tick() {

View File

@ -552,7 +552,9 @@ Unit::~Unit() {
Renderer &renderer= Renderer::getInstance();
renderer.removeUnitFromQuadCache(this);
game->removeUnitFromSelection(this);
if(game != NULL) {
game->removeUnitFromSelection(this);
}
//MutexSafeWrapper safeMutex1(&mutexDeletedUnits,string(__FILE__) + "_" + intToStr(__LINE__));
//deletedUnits[this]=true;

View File

@ -15,6 +15,7 @@
#include "leak_dumper.h"
#include "thread.h"
#include <string>
#include <map>
using namespace Shared::Platform;
using namespace std;
@ -41,6 +42,10 @@ protected:
Mutex mutexExecutingTask;
bool executingTask;
void *ptr;
static Mutex mutexMasterThreadList;
static std::map<void *,int> masterThreadList;
bool quit;
bool running;
string uniqueID;
@ -90,6 +95,8 @@ public:
T * getGenericData() { return genericData; }
template <typename T>
void setGenericData(T *value) { genericData = value; }
static bool isThreadDeleted(void *ptr);
};
class RunningStatusSafeWrapper {

View File

@ -20,9 +20,17 @@ using namespace Shared::Util;
namespace Shared { namespace PlatformCommon {
BaseThread::BaseThread() : Thread() {
Mutex BaseThread::mutexMasterThreadList;
std::map<void *,int> BaseThread::masterThreadList;
BaseThread::BaseThread() : Thread(), ptr(NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
ptr = this;
MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
masterThreadList[ptr]++;
safeMutexMasterList.ReleaseLock();
uniqueID = "base_thread";
setQuitStatus(false);
@ -39,6 +47,28 @@ BaseThread::~BaseThread() {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str());
bool ret = shutdownAndWait();
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] uniqueID [%s] ret [%d] END\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str(),ret);
MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
if(masterThreadList.find(this) == masterThreadList.end()) {
char szBuf[4096]="";
sprintf(szBuf,"invalid thread delete for ptr: %p",this);
throw runtime_error(szBuf);
}
masterThreadList[this]--;
if(masterThreadList[this] <= 0) {
masterThreadList.erase(this);
}
safeMutexMasterList.ReleaseLock();
}
bool BaseThread::isThreadDeleted(void *ptr) {
bool result = false;
MutexSafeWrapper safeMutexMasterList(&mutexMasterThreadList);
if(masterThreadList.find(ptr) != masterThreadList.end()) {
result = (masterThreadList[ptr] <= 0);
}
safeMutexMasterList.ReleaseLock();
return result;
}
Mutex * BaseThread::getMutexThreadOwnerValid() {
@ -180,7 +210,9 @@ void BaseThread::setDeleteSelfOnExecutionDone(bool value) {
void BaseThread::deleteSelfIfRequired() {
if(getDeleteSelfOnExecutionDone() == true) {
delete this;
if(isThreadDeleted(this->ptr) == false) {
delete this;
}
return;
}
}

View File

@ -358,6 +358,7 @@ bool SimpleTaskThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
}
void SimpleTaskThread::execute() {
void *ptr_cpy = this->ptr;
bool mustDeleteSelf = false;
{
{
@ -424,7 +425,9 @@ void SimpleTaskThread::execute() {
}
if(mustDeleteSelf == true) {
delete this;
if(isThreadDeleted(ptr_cpy) == false) {
delete this;
}
}
}
@ -486,6 +489,7 @@ bool LogFileThread::checkSaveCurrentLogBufferToDisk() {
}
void LogFileThread::execute() {
void *ptr_cpy = this->ptr;
bool mustDeleteSelf = false;
{
RunningStatusSafeWrapper runningStatus(this);
@ -531,7 +535,9 @@ void LogFileThread::execute() {
}
if(mustDeleteSelf == true) {
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] LogFile thread is deleting self\n",__FILE__,__FUNCTION__,__LINE__);
delete this;
if(isThreadDeleted(ptr_cpy) == false) {
delete this;
}
return;
}
}