1.1 --- a/core/ConVarManager.cpp Sat Jan 09 11:33:19 2010 -0800
1.2 +++ b/core/ConVarManager.cpp Sun Jan 10 16:58:17 2010 -0800
1.3 @@ -58,6 +58,40 @@
1.4 typedef List<const ConVar *> ConVarList;
1.5 KTrie<ConVarInfo *> convar_cache;
1.6
1.7 +class ConVarReentrancyGuard
1.8 +{
1.9 + ConVar *cvar;
1.10 + ConVarReentrancyGuard *up;
1.11 +public:
1.12 + static ConVarReentrancyGuard *chain;
1.13 +
1.14 + ConVarReentrancyGuard(ConVar *cvar)
1.15 + : cvar(cvar), up(chain)
1.16 + {
1.17 + chain = this;
1.18 + }
1.19 +
1.20 + ~ConVarReentrancyGuard()
1.21 + {
1.22 + assert(chain == this);
1.23 + chain = up;
1.24 + }
1.25 +
1.26 + static bool IsCvarInChain(ConVar *cvar)
1.27 + {
1.28 + ConVarReentrancyGuard *guard = chain;
1.29 + while (guard != NULL)
1.30 + {
1.31 + if (guard->cvar == cvar)
1.32 + return true;
1.33 + guard = guard->up;
1.34 + }
1.35 + return false;
1.36 + }
1.37 +};
1.38 +
1.39 +ConVarReentrancyGuard *ConVarReentrancyGuard::chain = NULL;
1.40 +
1.41 ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
1.42 {
1.43 }
1.44 @@ -536,7 +570,8 @@
1.45 }
1.46
1.47 /* If the forward now has 0 functions in it... */
1.48 - if (pForward->GetFunctionCount() == 0)
1.49 + if (pForward->GetFunctionCount() == 0 &&
1.50 + !ConVarReentrancyGuard::IsCvarInChain(pConVar))
1.51 {
1.52 /* Free this forward */
1.53 g_Forwards.ReleaseForward(pForward);
1.54 @@ -647,6 +682,8 @@
1.55
1.56 if (pForward != NULL)
1.57 {
1.58 + ConVarReentrancyGuard guard(pConVar);
1.59 +
1.60 /* Now call forwards in plugins that have hooked this */
1.61 pForward->PushCell(pInfo->handle);
1.62 pForward->PushString(oldValue);