core/ConVarManager.cpp
changeset 2890 54f2a62d6198
parent 2846 5e176efe7927
child 3367 18eb63085ca4
     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);