# HG changeset patch # User David Anderson # Date 1234069008 18000 # Node ID 2995c3b5d7b02f4923518d101ad266bdcd71095e # Parent e4cd7bb48e7c28c0a47044d7df9a2ddab1e4b7c9 Fixed EventManager holding onto stale pointers (bug 3548, r=ds). diff -r e4cd7bb48e7c -r 2995c3b5d7b0 core/EventManager.cpp --- a/core/EventManager.cpp Sun Feb 01 20:39:23 2009 -0500 +++ b/core/EventManager.cpp Sat Feb 07 23:56:48 2009 -0500 @@ -193,6 +193,9 @@ pHook->pPostHook->AddFunction(pFunction); } + /* Cache the name for post hooks */ + pHook->name = strdup(name); + /* Increase reference count */ pHook->refCount++; @@ -296,6 +299,9 @@ /* Delete entry in trie */ sm_trie_delete(m_EventHooks, name); + /* Free the cached name */ + free(pHook->name); + /* And finally free structure memory */ delete pHook; } @@ -365,14 +371,17 @@ { RETURN_META_VALUE(MRES_IGNORED, false); } - - /* Get the event name, we're going to need this for passing to post hooks */ + name = pEvent->GetName(); - - m_EventNames.push(name); - + if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast(&pHook))) { + /* Push the event onto the event stack. The reference count is increased to make sure + * the structure is not garbage collected in between now and the post hook. + */ + pHook->refCount++; + m_EventStack.push(pHook); + pForward = pHook->pPreHook; if (pForward) @@ -400,6 +409,10 @@ RETURN_META_VALUE(MRES_SUPERCEDE, false); } } + else + { + m_EventStack.push(NULL); + } RETURN_META_VALUE(MRES_IGNORED, true); } @@ -410,7 +423,6 @@ EventHook *pHook; EventInfo info; IChangeableForward *pForward; - const char *name; Handle_t hndl = 0; /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */ @@ -419,9 +431,9 @@ RETURN_META_VALUE(MRES_IGNORED, false); } - name = m_EventNames.front(); + pHook = m_EventStack.front(); - if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast(&pHook))) + if (pHook != NULL) { pForward = pHook->pPostHook; @@ -438,7 +450,7 @@ pForward->PushCell(BAD_HANDLE); } - pForward->PushString(name); + pForward->PushString(pHook->name); pForward->PushCell(bDontBroadcast); pForward->Execute(NULL); @@ -453,9 +465,19 @@ m_EventCopies.pop(); } } + + /* Decrement reference count, check if a delayed delete is needed */ + if (--pHook->refCount == 0) + { + assert(pHook->pPostHook == NULL); + assert(pHook->pPreHook == NULL); + sm_trie_delete(m_EventHooks, pHook->name); + free(pHook->name); + delete pHook; + } } - m_EventNames.pop(); + m_EventStack.pop(); RETURN_META_VALUE(MRES_IGNORED, true); } diff -r e4cd7bb48e7c -r 2995c3b5d7b0 core/EventManager.h --- a/core/EventManager.h Sun Feb 01 20:39:23 2009 -0500 +++ b/core/EventManager.h Sat Feb 07 23:56:48 2009 -0500 @@ -68,6 +68,7 @@ IChangeableForward *pPostHook; bool postCopy; unsigned int refCount; + char *name; }; enum EventHookMode @@ -124,7 +125,7 @@ HandleType_t m_EventType; Trie *m_EventHooks; CStack m_FreeEvents; - CStack m_EventNames; + CStack m_EventStack; CStack m_EventCopies; };