Fixed amb660 - crash on exit when handles were created for convars that belonged to Metamod:Source plugins (or SM extensions that were loaded as MM:S plugins)

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401151
This commit is contained in:
Scott Ehlert 2007-07-23 18:30:02 +00:00
parent 921bf64df2
commit b372d50f3c
4 changed files with 101 additions and 0 deletions

View File

@ -31,6 +31,10 @@ typedef List<const ConVar *> ConVarList;
ConVarManager::ConVarManager() : m_ConVarType(0), m_VSPIface(NULL), m_CanQueryConVars(false)
{
#if PLAPI_VERSION < 12
m_IgnoreHandle = false;
#endif
/* Create a convar lookup trie */
m_ConVarCache = sm_trie_create();
}
@ -127,6 +131,52 @@ void ConVarManager::OnSourceModVSPReceived(IServerPluginCallbacks *iface)
}
}
#if PLAPI_VERSION >= 12
void ConVarManager::OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand)
{
/* Only check convars that have not been created by SourceMod's core */
if (id != g_PLID && !pCommand->IsCommand())
{
ConVarInfo *pInfo;
HandleSecurity sec(NULL, g_pCoreIdent);
bool handleExists = sm_trie_retrieve(m_ConVarCache, pCommand->GetName(), reinterpret_cast<void **>(&pInfo));
if (handleExists)
{
g_HandleSys.FreeHandle(pInfo->handle, &sec);
}
}
}
#else
/* I truly detest this code */
void ConVarManager::OnMetamodPluginUnloaded(PluginId id)
{
ConVarInfo *pInfo;
const char *cvarName;
HandleSecurity sec(NULL, g_pCoreIdent);
List<ConVarInfo *>::iterator i;
for (i = m_ConVars.begin(); i != m_ConVars.end(); i++)
{
pInfo = (*i);
cvarName = pInfo->name;
if (!icvar->FindVar(cvarName))
{
m_IgnoreHandle = true;
g_HandleSys.FreeHandle(pInfo->handle, &sec);
sm_trie_delete(m_ConVarCache, cvarName);
m_ConVars.erase(i);
delete [] cvarName;
}
}
}
#endif
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
{
ConVarList *pConVarList;
@ -140,6 +190,15 @@ void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
{
#if PLAPI_VERSION < 12
/* Lovely workaround for our workaround! */
if (m_IgnoreHandle)
{
m_IgnoreHandle = false;
return;
}
#endif
ConVarInfo *info;
ConVar *pConVar = static_cast<ConVar *>(object);
@ -235,6 +294,9 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
pInfo->sourceMod = false;
pInfo->pChangeForward = NULL;
pInfo->origCallback = pConVar->GetCallback();
#if PLAPI_VERSION < 12
pInfo->name = sm_strdup(pConVar->GetName());
#endif
/* Insert struct into caches */
m_ConVars.push_back(pInfo);
@ -310,6 +372,9 @@ Handle_t ConVarManager::FindConVar(const char *name)
pInfo->sourceMod = false;
pInfo->pChangeForward = NULL;
pInfo->origCallback = pConVar->GetCallback();
#if PLAPI_VERSION < 12
pInfo->name = sm_strdup(pConVar->GetName());
#endif
/* Insert struct into our caches */
m_ConVars.push_back(pInfo);

View File

@ -35,6 +35,9 @@ struct ConVarInfo
bool sourceMod; /**< Determines whether or not convar was created by a SourceMod plugin */
IChangeableForward *pChangeForward; /**< Forward associated with convar */
FnChangeCallback origCallback; /**< The original callback function */
#if PLAPI_VERSION < 12
const char *name; /**< Name of convar */
#endif
};
/**
@ -109,6 +112,18 @@ public:
*/
QueryCvarCookie_t QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback,
Handle_t hndl);
#if PLAPI_VERSION >= 12
/**
* Called when Metamod:Source is about to remove convar
*/
void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand);
#else
/**
* Called when Metamod:Source has unloaded a plugin
*/
void OnMetamodPluginUnloaded(PluginId id);
#endif
private:
/**
* Adds a convar to a plugin's list.
@ -132,6 +147,9 @@ private:
Trie *m_ConVarCache;
IServerPluginCallbacks *m_VSPIface;
bool m_CanQueryConVars;
#if PLAPI_VERSION < 12
bool m_IgnoreHandle;
#endif
};
extern ConVarManager g_ConVarManager;

View File

@ -17,6 +17,7 @@
#include "sm_version.h"
#include "sourcemod.h"
#include "Logger.h"
#include "ConVarManager.h"
SourceMod_Core g_SourceMod_Core;
IVEngineServer *engine = NULL;
@ -148,3 +149,15 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface)
pBase = pBase->m_pGlobalClassNext;
}
}
#if PLAPI_VERSION >= 12
void SourceMod_Core::OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand)
{
g_ConVarManager.OnUnlinkConCommandBase(id, pCommand);
}
#else
void SourceMod_Core::OnPluginUnload(PluginId id)
{
g_ConVarManager.OnMetamodPluginUnloaded(id);
}
#endif

View File

@ -49,6 +49,11 @@ public:
const char *GetLogTag();
public:
void OnVSPListening(IServerPluginCallbacks *iface);
#if PLAPI_VERSION >= 12
void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand);
#else
void OnPluginUnload(PluginId id);
#endif
};
extern SourceMod_Core g_SourceMod_Core;