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:
parent
b0a32b39c2
commit
d1dea716a6
@ -285,6 +285,7 @@ HandleError HandleSystem::MakePrimHandle(HandleType_t type,
|
|||||||
pHandle->owner = owner;
|
pHandle->owner = owner;
|
||||||
pHandle->ch_next = 0;
|
pHandle->ch_next = 0;
|
||||||
pHandle->access_special = false;
|
pHandle->access_special = false;
|
||||||
|
pHandle->is_destroying = false;
|
||||||
|
|
||||||
/* Create the hash value */
|
/* Create the hash value */
|
||||||
Handle_t hash = pHandle->serial;
|
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... */
|
/* Type should be the same but do this anyway... */
|
||||||
pType = &m_Types[pMaster->type];
|
pType = &m_Types[pMaster->type];
|
||||||
|
pMaster->is_destroying = true;
|
||||||
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
|
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
|
||||||
ReleasePrimHandle(master);
|
ReleasePrimHandle(master);
|
||||||
}
|
}
|
||||||
@ -613,6 +615,7 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
|||||||
/* Decrement, free if necessary */
|
/* Decrement, free if necessary */
|
||||||
if (--pHandle->refcount == 0)
|
if (--pHandle->refcount == 0)
|
||||||
{
|
{
|
||||||
|
pHandle->is_destroying = true;
|
||||||
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
|
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
|
||||||
ReleasePrimHandle(index);
|
ReleasePrimHandle(index);
|
||||||
} else {
|
} else {
|
||||||
@ -646,6 +649,14 @@ HandleError HandleSystem::FreeHandle(Handle_t handle, const HandleSecurity *pSec
|
|||||||
return HandleError_Access;
|
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);
|
return FreeHandle(pHandle, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ struct QHandle
|
|||||||
unsigned int clone; /* If non-zero, this is our cloned parent index */
|
unsigned int clone; /* If non-zero, this is our cloned parent index */
|
||||||
HandleSet set; /* Information about the handle's state */
|
HandleSet set; /* Information about the handle's state */
|
||||||
bool access_special; /* Whether or not access rules are special or type-derived */
|
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 */
|
HandleAccess sec; /* Security rules */
|
||||||
/* The following variables are unrelated to the Handle array, and used
|
/* The following variables are unrelated to the Handle array, and used
|
||||||
* as an inlined chain of information */
|
* as an inlined chain of information */
|
||||||
|
Loading…
Reference in New Issue
Block a user