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
This commit is contained in:
David Anderson 2007-05-13 22:36:22 +00:00
parent b0a32b39c2
commit d1dea716a6
2 changed files with 12 additions and 0 deletions

View File

@ -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);
}

View File

@ -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 */