Fix a number of issues with cloned handles (bug 5240, r=asherkin).
This commit is contained in:
parent
b3e48b0ad7
commit
e3d2ddf278
@ -579,6 +579,7 @@ HandleError HandleSystem::CloneHandle(QHandle *pHandle, unsigned int index, Hand
|
|||||||
}
|
}
|
||||||
|
|
||||||
pNewHandle->clone = index;
|
pNewHandle->clone = index;
|
||||||
|
pNewHandle->object = NULL;
|
||||||
pHandle->refcount++;
|
pHandle->refcount++;
|
||||||
|
|
||||||
*newhandle = new_handle;
|
*newhandle = new_handle;
|
||||||
@ -659,6 +660,14 @@ void HandleSystem::GetHandleUnchecked(Handle_t hndl, QHandle *& pHandle, unsigne
|
|||||||
|
|
||||||
HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
||||||
{
|
{
|
||||||
|
if (pHandle->is_destroying)
|
||||||
|
{
|
||||||
|
/* Someone tried to free this recursively.
|
||||||
|
* We'll just ignore this safely.
|
||||||
|
*/
|
||||||
|
return HandleError_None;
|
||||||
|
}
|
||||||
|
|
||||||
QHandleType *pType = &m_Types[pHandle->type];
|
QHandleType *pType = &m_Types[pHandle->type];
|
||||||
|
|
||||||
if (pHandle->clone)
|
if (pHandle->clone)
|
||||||
@ -673,6 +682,7 @@ HandleError HandleSystem::FreeHandle(QHandle *pHandle, unsigned int index)
|
|||||||
pMaster = &m_Handles[master];
|
pMaster = &m_Handles[master];
|
||||||
|
|
||||||
/* Release the clone now */
|
/* Release the clone now */
|
||||||
|
pHandle->is_destroying = true;
|
||||||
ReleasePrimHandle(index);
|
ReleasePrimHandle(index);
|
||||||
|
|
||||||
/* Decrement the master's reference count */
|
/* Decrement the master's reference count */
|
||||||
@ -681,20 +691,27 @@ 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;
|
pMaster->is_destroying = true;
|
||||||
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
|
if (pMaster->object)
|
||||||
|
{
|
||||||
|
pType->dispatch->OnHandleDestroy(pMaster->type, pMaster->object);
|
||||||
|
}
|
||||||
ReleasePrimHandle(master);
|
ReleasePrimHandle(master);
|
||||||
}
|
}
|
||||||
} else if (pHandle->set == HandleSet_Identity) {
|
} else if (pHandle->set == HandleSet_Identity) {
|
||||||
/* If we're an identity, skip all this stuff!
|
/* If we're an identity, skip all this stuff!
|
||||||
* NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR
|
* NOTE: SHARESYS DOES NOT CARE ABOUT THE DESTRUCTOR
|
||||||
*/
|
*/
|
||||||
|
pHandle->is_destroying = true;
|
||||||
ReleasePrimHandle(index);
|
ReleasePrimHandle(index);
|
||||||
} else {
|
} else {
|
||||||
/* Decrement, free if necessary */
|
/* Decrement, free if necessary */
|
||||||
if (--pHandle->refcount == 0)
|
if (--pHandle->refcount == 0)
|
||||||
{
|
{
|
||||||
pHandle->is_destroying = true;
|
pHandle->is_destroying = true;
|
||||||
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
|
if (pHandle->object)
|
||||||
|
{
|
||||||
|
pType->dispatch->OnHandleDestroy(pHandle->type, pHandle->object);
|
||||||
|
}
|
||||||
ReleasePrimHandle(index);
|
ReleasePrimHandle(index);
|
||||||
} else {
|
} else {
|
||||||
/* We must be cloned, so mark ourselves as freed */
|
/* We must be cloned, so mark ourselves as freed */
|
||||||
@ -727,14 +744,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -793,6 +802,9 @@ void HandleSystem::UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index)
|
|||||||
assert(pHandle->owner == 0);
|
assert(pHandle->owner == 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pHandle->owner = NULL;
|
||||||
|
|
||||||
/* Note that since 0 is an invalid handle, if any of these links are 0,
|
/* Note that since 0 is an invalid handle, if any of these links are 0,
|
||||||
* the data can still be set.
|
* the data can still be set.
|
||||||
*/
|
*/
|
||||||
@ -917,29 +929,9 @@ bool HandleSystem::RemoveType(HandleType_t type, IdentityToken_t *ident)
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pHandle->clone)
|
|
||||||
{
|
FreeHandle(pHandle, i);
|
||||||
/* Get parent */
|
|
||||||
QHandle *pOther = &m_Handles[pHandle->clone];
|
|
||||||
if (--pOther->refcount == 0)
|
|
||||||
{
|
|
||||||
/* Free! */
|
|
||||||
dispatch->OnHandleDestroy(type, pOther->object);
|
|
||||||
ReleasePrimHandle(pHandle->clone);
|
|
||||||
}
|
|
||||||
/* Unlink ourselves since we don't have a reference count */
|
|
||||||
ReleasePrimHandle(i);
|
|
||||||
} else {
|
|
||||||
/* If it's not a clone, we still have to check the reference count.
|
|
||||||
* Either way, we'll be destroyed eventually because the handle types do not change.
|
|
||||||
*/
|
|
||||||
if (--pHandle->refcount == 0)
|
|
||||||
{
|
|
||||||
/* Free! */
|
|
||||||
dispatch->OnHandleDestroy(type, pHandle->object);
|
|
||||||
ReleasePrimHandle(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pType->opened == 0)
|
if (pType->opened == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user