Fixed EventManager holding onto stale pointers (bug 3548, r=ds).
Fixed EventManager holding onto stale pointers (
bug 3548, r=ds).
1.1 --- a/core/EventManager.cpp Sun Feb 01 20:39:23 2009 -0500
1.2 +++ b/core/EventManager.cpp Sat Feb 07 23:56:48 2009 -0500
1.3 @@ -193,6 +193,9 @@
1.4 pHook->pPostHook->AddFunction(pFunction);
1.5 }
1.6
1.7 + /* Cache the name for post hooks */
1.8 + pHook->name = strdup(name);
1.9 +
1.10 /* Increase reference count */
1.11 pHook->refCount++;
1.12
1.13 @@ -296,6 +299,9 @@
1.14 /* Delete entry in trie */
1.15 sm_trie_delete(m_EventHooks, name);
1.16
1.17 + /* Free the cached name */
1.18 + free(pHook->name);
1.19 +
1.20 /* And finally free structure memory */
1.21 delete pHook;
1.22 }
1.23 @@ -365,14 +371,17 @@
1.24 {
1.25 RETURN_META_VALUE(MRES_IGNORED, false);
1.26 }
1.27 -
1.28 - /* Get the event name, we're going to need this for passing to post hooks */
1.29 +
1.30 name = pEvent->GetName();
1.31 -
1.32 - m_EventNames.push(name);
1.33 -
1.34 +
1.35 if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
1.36 {
1.37 + /* Push the event onto the event stack. The reference count is increased to make sure
1.38 + * the structure is not garbage collected in between now and the post hook.
1.39 + */
1.40 + pHook->refCount++;
1.41 + m_EventStack.push(pHook);
1.42 +
1.43 pForward = pHook->pPreHook;
1.44
1.45 if (pForward)
1.46 @@ -400,6 +409,10 @@
1.47 RETURN_META_VALUE(MRES_SUPERCEDE, false);
1.48 }
1.49 }
1.50 + else
1.51 + {
1.52 + m_EventStack.push(NULL);
1.53 + }
1.54
1.55 RETURN_META_VALUE(MRES_IGNORED, true);
1.56 }
1.57 @@ -410,7 +423,6 @@
1.58 EventHook *pHook;
1.59 EventInfo info;
1.60 IChangeableForward *pForward;
1.61 - const char *name;
1.62 Handle_t hndl = 0;
1.63
1.64 /* The engine accepts NULL without crashing, so to prevent a crash in SM we ignore these */
1.65 @@ -419,9 +431,9 @@
1.66 RETURN_META_VALUE(MRES_IGNORED, false);
1.67 }
1.68
1.69 - name = m_EventNames.front();
1.70 + pHook = m_EventStack.front();
1.71
1.72 - if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
1.73 + if (pHook != NULL)
1.74 {
1.75 pForward = pHook->pPostHook;
1.76
1.77 @@ -438,7 +450,7 @@
1.78 pForward->PushCell(BAD_HANDLE);
1.79 }
1.80
1.81 - pForward->PushString(name);
1.82 + pForward->PushString(pHook->name);
1.83 pForward->PushCell(bDontBroadcast);
1.84 pForward->Execute(NULL);
1.85
1.86 @@ -453,9 +465,19 @@
1.87 m_EventCopies.pop();
1.88 }
1.89 }
1.90 +
1.91 + /* Decrement reference count, check if a delayed delete is needed */
1.92 + if (--pHook->refCount == 0)
1.93 + {
1.94 + assert(pHook->pPostHook == NULL);
1.95 + assert(pHook->pPreHook == NULL);
1.96 + sm_trie_delete(m_EventHooks, pHook->name);
1.97 + free(pHook->name);
1.98 + delete pHook;
1.99 + }
1.100 }
1.101
1.102 - m_EventNames.pop();
1.103 + m_EventStack.pop();
1.104
1.105 RETURN_META_VALUE(MRES_IGNORED, true);
1.106 }
2.1 --- a/core/EventManager.h Sun Feb 01 20:39:23 2009 -0500
2.2 +++ b/core/EventManager.h Sat Feb 07 23:56:48 2009 -0500
2.3 @@ -68,6 +68,7 @@
2.4 IChangeableForward *pPostHook;
2.5 bool postCopy;
2.6 unsigned int refCount;
2.7 + char *name;
2.8 };
2.9
2.10 enum EventHookMode
2.11 @@ -124,7 +125,7 @@
2.12 HandleType_t m_EventType;
2.13 Trie *m_EventHooks;
2.14 CStack<EventInfo *> m_FreeEvents;
2.15 - CStack<const char *> m_EventNames;
2.16 + CStack<EventHook *> m_EventStack;
2.17 CStack<IGameEvent *> m_EventCopies;
2.18 };
2.19