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)
|
ConVarManager::ConVarManager() : m_ConVarType(0), m_VSPIface(NULL), m_CanQueryConVars(false)
|
||||||
{
|
{
|
||||||
|
#if PLAPI_VERSION < 12
|
||||||
|
m_IgnoreHandle = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create a convar lookup trie */
|
/* Create a convar lookup trie */
|
||||||
m_ConVarCache = sm_trie_create();
|
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)
|
void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
||||||
{
|
{
|
||||||
ConVarList *pConVarList;
|
ConVarList *pConVarList;
|
||||||
@ -140,6 +190,15 @@ void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
|
|||||||
|
|
||||||
void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
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;
|
ConVarInfo *info;
|
||||||
ConVar *pConVar = static_cast<ConVar *>(object);
|
ConVar *pConVar = static_cast<ConVar *>(object);
|
||||||
|
|
||||||
@ -235,6 +294,9 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
|||||||
pInfo->sourceMod = false;
|
pInfo->sourceMod = false;
|
||||||
pInfo->pChangeForward = NULL;
|
pInfo->pChangeForward = NULL;
|
||||||
pInfo->origCallback = pConVar->GetCallback();
|
pInfo->origCallback = pConVar->GetCallback();
|
||||||
|
#if PLAPI_VERSION < 12
|
||||||
|
pInfo->name = sm_strdup(pConVar->GetName());
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Insert struct into caches */
|
/* Insert struct into caches */
|
||||||
m_ConVars.push_back(pInfo);
|
m_ConVars.push_back(pInfo);
|
||||||
@ -310,6 +372,9 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
|||||||
pInfo->sourceMod = false;
|
pInfo->sourceMod = false;
|
||||||
pInfo->pChangeForward = NULL;
|
pInfo->pChangeForward = NULL;
|
||||||
pInfo->origCallback = pConVar->GetCallback();
|
pInfo->origCallback = pConVar->GetCallback();
|
||||||
|
#if PLAPI_VERSION < 12
|
||||||
|
pInfo->name = sm_strdup(pConVar->GetName());
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Insert struct into our caches */
|
/* Insert struct into our caches */
|
||||||
m_ConVars.push_back(pInfo);
|
m_ConVars.push_back(pInfo);
|
||||||
|
@ -35,6 +35,9 @@ struct ConVarInfo
|
|||||||
bool sourceMod; /**< Determines whether or not convar was created by a SourceMod plugin */
|
bool sourceMod; /**< Determines whether or not convar was created by a SourceMod plugin */
|
||||||
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
||||||
FnChangeCallback origCallback; /**< The original callback function */
|
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,
|
QueryCvarCookie_t QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback,
|
||||||
Handle_t hndl);
|
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:
|
private:
|
||||||
/**
|
/**
|
||||||
* Adds a convar to a plugin's list.
|
* Adds a convar to a plugin's list.
|
||||||
@ -132,6 +147,9 @@ private:
|
|||||||
Trie *m_ConVarCache;
|
Trie *m_ConVarCache;
|
||||||
IServerPluginCallbacks *m_VSPIface;
|
IServerPluginCallbacks *m_VSPIface;
|
||||||
bool m_CanQueryConVars;
|
bool m_CanQueryConVars;
|
||||||
|
#if PLAPI_VERSION < 12
|
||||||
|
bool m_IgnoreHandle;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ConVarManager g_ConVarManager;
|
extern ConVarManager g_ConVarManager;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "sm_version.h"
|
#include "sm_version.h"
|
||||||
#include "sourcemod.h"
|
#include "sourcemod.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "ConVarManager.h"
|
||||||
|
|
||||||
SourceMod_Core g_SourceMod_Core;
|
SourceMod_Core g_SourceMod_Core;
|
||||||
IVEngineServer *engine = NULL;
|
IVEngineServer *engine = NULL;
|
||||||
@ -148,3 +149,15 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface)
|
|||||||
pBase = pBase->m_pGlobalClassNext;
|
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();
|
const char *GetLogTag();
|
||||||
public:
|
public:
|
||||||
void OnVSPListening(IServerPluginCallbacks *iface);
|
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;
|
extern SourceMod_Core g_SourceMod_Core;
|
||||||
|
Loading…
Reference in New Issue
Block a user