From d1dea716a60fce4f6c2db2094f0db1ff7c6bf082 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 13 May 2007 22:36:22 +0000 Subject: [PATCH] Added a re-entrancy check to Handles so the destructor won't fire twice in certain cases --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40795 --- core/systems/HandleSys.cpp | 11 +++++++++++ core/systems/HandleSys.h | 1 + 2 files changed, 12 insertions(+) diff --git a/core/systems/HandleSys.cpp b/core/systems/HandleSys.cpp index dea38e9b..d6a7e934 100644 --- a/core/systems/HandleSys.cpp +++ b/core/systems/HandleSys.cpp @@ -285,6 +285,7 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type, pHandle->owner = owner; pHandle->ch_next = 0; pHandle->access_special = false; + pHandle->is_destroying = false; /* Create the hash value */ Handle_t hash = pHandle->serial; @@ -601,6 +602,7 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index) { /* Type should be the same but do this anyway... */ pType = &m_Types[pMaster->type]; + pMaster->is_destroying = true; pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object); ReleasePrimHandle(master); } @@ -613,6 +615,7 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index) /* Decrement, free if necessary */ if (--pHandle->refcount == 0) { + pHandle->is_destroying = true; pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object); ReleasePrimHandle(index); } else { @@ -646,6 +649,14 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, const HandleSecurity *pSec return HandleError_Access; } + if (pHandle->is_destroying) + { + /* Someone tried to free this recursively. + * We'll just ignore this safely. + */ + return HandleError_None; + } + return FreeHandle(pHandle, index); } diff --git a/core/systems/HandleSys.h b/core/systems/HandleSys.h index 826c88b7..1837f5cb 100644 --- a/core/systems/HandleSys.h +++ b/core/systems/HandleSys.h @@ -65,6 +65,7 @@ struct QHandle unsigned int clone; /* If non-zero, this is our cloned parent index */ HandleSet set; /* Information about the handle's state */ bool access_special; /* Whether or not access rules are special or type-derived */ + bool is_destroying; /* Whether or not the handle is being destroyed */ HandleAccess sec; /* Security rules */ /* The following variables are unrelated to the Handle array, and used * as an inlined chain of information */