Fixed a crash in the Event Manager when a game fired an event from a listener that was looking for the same event (bug 3468, r=me).

In other words it was a problem where our FireEvent hooks were being re-entered for the _same_ game event. The Event Manager was not able to handle this and crashed.
This commit is contained in:
Scott Ehlert 2009-01-27 23:53:48 -06:00
parent a8e1a4f2fd
commit 7167a807bf
2 changed files with 16 additions and 12 deletions

View File

@ -377,21 +377,21 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
if (pForward) if (pForward)
{ {
EventInfo info = { pEvent, NULL }; EventInfo info(pEvent, NULL);
HandleSecurity sec(NULL, g_pCoreIdent);
Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); Handle_t hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
pForward->PushCell(hndl); pForward->PushCell(hndl);
pForward->PushString(name); pForward->PushString(name);
pForward->PushCell(bDontBroadcast); pForward->PushCell(bDontBroadcast);
pForward->Execute(&res, NULL); pForward->Execute(&res, NULL);
HandleSecurity sec(NULL, g_pCoreIdent);
g_HandleSys.FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
} }
if (pHook->postCopy) if (pHook->postCopy)
{ {
pHook->pEventCopy = gameevents->DuplicateEvent(pEvent); m_EventCopies.push(gameevents->DuplicateEvent(pEvent));
} }
if (res) if (res)
@ -407,8 +407,8 @@ bool EventManager::OnFireEvent(IGameEvent *pEvent, bool bDontBroadcast)
/* IGameEventManager2::FireEvent post hook */ /* IGameEventManager2::FireEvent post hook */
bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast) bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
{ {
IGameEvent *pEventCopy = NULL;
EventHook *pHook; EventHook *pHook;
EventInfo info;
IChangeableForward *pForward; IChangeableForward *pForward;
const char *name; const char *name;
Handle_t hndl = 0; Handle_t hndl = 0;
@ -424,14 +424,13 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook))) if (sm_trie_retrieve(m_EventHooks, name, reinterpret_cast<void **>(&pHook)))
{ {
pForward = pHook->pPostHook; pForward = pHook->pPostHook;
pEventCopy = pHook->pEventCopy;
if (pForward) if (pForward)
{ {
EventInfo info = { pEventCopy, NULL };
if (pHook->postCopy) if (pHook->postCopy)
{ {
info.pEvent = m_EventCopies.front();
info.pOwner = NULL;
hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL); hndl = g_HandleSys.CreateHandle(m_EventType, &info, NULL, g_pCoreIdent, NULL);
pForward->PushCell(hndl); pForward->PushCell(hndl);
@ -450,8 +449,8 @@ bool EventManager::OnFireEvent_Post(IGameEvent *pEvent, bool bDontBroadcast)
g_HandleSys.FreeHandle(hndl, &sec); g_HandleSys.FreeHandle(hndl, &sec);
/* Free event structure */ /* Free event structure */
gameevents->FreeEvent(pEventCopy); gameevents->FreeEvent(info.pEvent);
pHook->pEventCopy = NULL; m_EventCopies.pop();
} }
} }
} }

View File

@ -45,6 +45,12 @@ using namespace SourceHook;
struct EventInfo struct EventInfo
{ {
EventInfo()
{
}
EventInfo(IGameEvent *ev, IdentityToken_t *owner) : pEvent(ev), pOwner(owner)
{
}
IGameEvent *pEvent; IGameEvent *pEvent;
IdentityToken_t *pOwner; IdentityToken_t *pOwner;
}; };
@ -56,13 +62,11 @@ struct EventHook
pPreHook = NULL; pPreHook = NULL;
pPostHook = NULL; pPostHook = NULL;
postCopy = false; postCopy = false;
pEventCopy = NULL;
refCount = 0; refCount = 0;
} }
IChangeableForward *pPreHook; IChangeableForward *pPreHook;
IChangeableForward *pPostHook; IChangeableForward *pPostHook;
bool postCopy; bool postCopy;
IGameEvent *pEventCopy;
unsigned int refCount; unsigned int refCount;
}; };
@ -121,6 +125,7 @@ private:
Trie *m_EventHooks; Trie *m_EventHooks;
CStack<EventInfo *> m_FreeEvents; CStack<EventInfo *> m_FreeEvents;
CStack<const char *> m_EventNames; CStack<const char *> m_EventNames;
CStack<IGameEvent *> m_EventCopies;
}; };
extern EventManager g_EventManager; extern EventManager g_EventManager;