- 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:
parent
76c3fa1949
commit
9aca26a0f0
|
@ -1676,14 +1676,29 @@ void Game::renderWorker() {
|
||||||
// ==================== tick ====================
|
// ==================== tick ====================
|
||||||
|
|
||||||
void Game::removeUnitFromSelection(const Unit *unit) {
|
void Game::removeUnitFromSelection(const Unit *unit) {
|
||||||
Selection *selection= getGuiPtr()->getSelectionPtr();
|
try {
|
||||||
for(int i=0; i < selection->getCount(); ++i) {
|
Selection *selection= gui.getSelectionPtr();
|
||||||
const Unit *currentUnit = selection->getUnit(i);
|
for(int i=0; i < selection->getCount(); ++i) {
|
||||||
if(currentUnit == unit) {
|
const Unit *currentUnit = selection->getUnit(i);
|
||||||
selection->unSelect(i);
|
if(currentUnit == unit) {
|
||||||
break;
|
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() {
|
void Game::tick() {
|
||||||
|
|
|
@ -552,7 +552,9 @@ Unit::~Unit() {
|
||||||
|
|
||||||
Renderer &renderer= Renderer::getInstance();
|
Renderer &renderer= Renderer::getInstance();
|
||||||
renderer.removeUnitFromQuadCache(this);
|
renderer.removeUnitFromQuadCache(this);
|
||||||
game->removeUnitFromSelection(this);
|
if(game != NULL) {
|
||||||
|
game->removeUnitFromSelection(this);
|
||||||
|
}
|
||||||
|
|
||||||
//MutexSafeWrapper safeMutex1(&mutexDeletedUnits,string(__FILE__) + "_" + intToStr(__LINE__));
|
//MutexSafeWrapper safeMutex1(&mutexDeletedUnits,string(__FILE__) + "_" + intToStr(__LINE__));
|
||||||
//deletedUnits[this]=true;
|
//deletedUnits[this]=true;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
using namespace Shared::Platform;
|
using namespace Shared::Platform;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -41,6 +42,10 @@ protected:
|
||||||
Mutex mutexExecutingTask;
|
Mutex mutexExecutingTask;
|
||||||
bool executingTask;
|
bool executingTask;
|
||||||
|
|
||||||
|
void *ptr;
|
||||||
|
static Mutex mutexMasterThreadList;
|
||||||
|
static std::map<void *,int> masterThreadList;
|
||||||
|
|
||||||
bool quit;
|
bool quit;
|
||||||
bool running;
|
bool running;
|
||||||
string uniqueID;
|
string uniqueID;
|
||||||
|
@ -90,6 +95,8 @@ public:
|
||||||
T * getGenericData() { return genericData; }
|
T * getGenericData() { return genericData; }
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void setGenericData(T *value) { genericData = value; }
|
void setGenericData(T *value) { genericData = value; }
|
||||||
|
|
||||||
|
static bool isThreadDeleted(void *ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RunningStatusSafeWrapper {
|
class RunningStatusSafeWrapper {
|
||||||
|
|
|
@ -20,9 +20,17 @@ using namespace Shared::Util;
|
||||||
|
|
||||||
namespace Shared { namespace PlatformCommon {
|
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__);
|
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";
|
uniqueID = "base_thread";
|
||||||
|
|
||||||
setQuitStatus(false);
|
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());
|
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();
|
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);
|
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() {
|
Mutex * BaseThread::getMutexThreadOwnerValid() {
|
||||||
|
@ -180,7 +210,9 @@ void BaseThread::setDeleteSelfOnExecutionDone(bool value) {
|
||||||
|
|
||||||
void BaseThread::deleteSelfIfRequired() {
|
void BaseThread::deleteSelfIfRequired() {
|
||||||
if(getDeleteSelfOnExecutionDone() == true) {
|
if(getDeleteSelfOnExecutionDone() == true) {
|
||||||
delete this;
|
if(isThreadDeleted(this->ptr) == false) {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,6 +358,7 @@ bool SimpleTaskThread::canShutdown(bool deleteSelfIfShutdownDelayed) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleTaskThread::execute() {
|
void SimpleTaskThread::execute() {
|
||||||
|
void *ptr_cpy = this->ptr;
|
||||||
bool mustDeleteSelf = false;
|
bool mustDeleteSelf = false;
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -424,7 +425,9 @@ void SimpleTaskThread::execute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mustDeleteSelf == true) {
|
if(mustDeleteSelf == true) {
|
||||||
delete this;
|
if(isThreadDeleted(ptr_cpy) == false) {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,6 +489,7 @@ bool LogFileThread::checkSaveCurrentLogBufferToDisk() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogFileThread::execute() {
|
void LogFileThread::execute() {
|
||||||
|
void *ptr_cpy = this->ptr;
|
||||||
bool mustDeleteSelf = false;
|
bool mustDeleteSelf = false;
|
||||||
{
|
{
|
||||||
RunningStatusSafeWrapper runningStatus(this);
|
RunningStatusSafeWrapper runningStatus(this);
|
||||||
|
@ -531,7 +535,9 @@ void LogFileThread::execute() {
|
||||||
}
|
}
|
||||||
if(mustDeleteSelf == true) {
|
if(mustDeleteSelf == true) {
|
||||||
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] LogFile thread is deleting self\n",__FILE__,__FUNCTION__,__LINE__);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue