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:
parent
921bf64df2
commit
b372d50f3c
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user