Fix various problems with unloading ClientPrefs and SourceMod (bug 5874, r=ds).
--HG-- extra : rebase_source : 0a35f8380d651ca65fac9dd402c5cd3625e3105c
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod Client Preferences Extension
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -55,35 +55,12 @@ void CookieManager::Unload()
|
||||
for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
|
||||
{
|
||||
if (connected[i])
|
||||
{
|
||||
OnClientDisconnecting(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find all cookies and delete them */
|
||||
Cookie *current;
|
||||
|
||||
for (SourceHook::List<Cookie *>::iterator _iter = cookieList.begin(); _iter != cookieList.end(); _iter++)
|
||||
{
|
||||
current = (Cookie *)*_iter;
|
||||
|
||||
if (current == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
g_ClientPrefs.cookieMutex->Lock();
|
||||
if (current->usedInQuery)
|
||||
{
|
||||
current->shouldDelete = true;
|
||||
g_ClientPrefs.cookieMutex->Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ClientPrefs.cookieMutex->Unlock();
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
delete (*_iter);
|
||||
|
||||
cookieList.clear();
|
||||
}
|
||||
@@ -93,9 +70,7 @@ Cookie *CookieManager::FindCookie(const char *name)
|
||||
Cookie **pCookie = cookieTrie.retrieve(name);
|
||||
|
||||
if (pCookie == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return *pCookie;
|
||||
}
|
||||
@@ -116,7 +91,6 @@ Cookie *CookieManager::CreateCookie(const char *name, const char *description, C
|
||||
|
||||
/* First time cookie - Create from scratch */
|
||||
pCookie = new Cookie(name, description, access);
|
||||
pCookie->usedInQuery++;
|
||||
|
||||
/* Attempt to insert cookie into the db and get its ID num */
|
||||
TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
|
||||
|
||||
@@ -75,12 +75,7 @@ struct Cookie
|
||||
dbid = -1;
|
||||
|
||||
for (int i=0; i<=MAXCLIENTS; i++)
|
||||
{
|
||||
data[i] = NULL;
|
||||
}
|
||||
|
||||
shouldDelete = false;
|
||||
usedInQuery = 0;
|
||||
}
|
||||
|
||||
~Cookie()
|
||||
@@ -88,9 +83,7 @@ struct Cookie
|
||||
for (int i=0; i<=MAXCLIENTS; i++)
|
||||
{
|
||||
if (data[i] != NULL)
|
||||
{
|
||||
delete data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,10 +92,6 @@ struct Cookie
|
||||
int dbid;
|
||||
CookieData *data[MAXCLIENTS+1];
|
||||
CookieAccess access;
|
||||
|
||||
/* Reference counting stuff */
|
||||
bool shouldDelete;
|
||||
int usedInQuery;
|
||||
};
|
||||
|
||||
class CookieManager : public IClientListener, public IPluginsListener
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod Client Preferences Extension
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -50,9 +50,6 @@ DbDriver g_DriverType;
|
||||
|
||||
bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
{
|
||||
queryMutex = threader->MakeMutex();
|
||||
cookieMutex = threader->MakeMutex();
|
||||
|
||||
DBInfo = dbi->FindDatabaseConf("clientprefs");
|
||||
|
||||
if (DBInfo == NULL)
|
||||
@@ -155,13 +152,15 @@ void ClientPrefs::NotifyInterfaceDrop(SMInterface *pInterface)
|
||||
}
|
||||
}
|
||||
|
||||
void ClientPrefs::SDK_OnUnload()
|
||||
void ClientPrefs::SDK_OnDependenciesDropped()
|
||||
{
|
||||
// At this point, we're guaranteed that DBI has flushed the worker thread
|
||||
// for us, so no cookies should have outstanding queries.
|
||||
g_CookieManager.Unload();
|
||||
|
||||
handlesys->RemoveType(g_CookieType, myself->GetIdentity());
|
||||
handlesys->RemoveType(g_CookieIterator, myself->GetIdentity());
|
||||
|
||||
g_CookieManager.Unload();
|
||||
|
||||
if (Database != NULL)
|
||||
{
|
||||
Database->Close();
|
||||
@@ -199,9 +198,6 @@ void ClientPrefs::SDK_OnUnload()
|
||||
|
||||
plsys->RemovePluginsListener(&g_CookieManager);
|
||||
playerhelpers->RemoveClientListener(&g_CookieManager);
|
||||
|
||||
queryMutex->DestroyThis();
|
||||
cookieMutex->DestroyThis();
|
||||
}
|
||||
|
||||
void ClientPrefs::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
|
||||
@@ -312,7 +308,11 @@ void ClientPrefs::DatabaseConnect()
|
||||
|
||||
databaseLoading = false;
|
||||
|
||||
this->ProcessQueryCache();
|
||||
// Need a new scope because of the goto above.
|
||||
{
|
||||
ke::AutoLock lock(&queryLock);
|
||||
this->ProcessQueryCache();
|
||||
}
|
||||
return;
|
||||
|
||||
fatal_fail:
|
||||
@@ -321,24 +321,18 @@ fatal_fail:
|
||||
databaseLoading = false;
|
||||
}
|
||||
|
||||
bool ClientPrefs::AddQueryToQueue( TQueryOp *query )
|
||||
bool ClientPrefs::AddQueryToQueue(TQueryOp *query)
|
||||
{
|
||||
queryMutex->Lock();
|
||||
if (Database == NULL)
|
||||
{
|
||||
cachedQueries.push_back(query);
|
||||
queryMutex->Unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cachedQueries.empty())
|
||||
{
|
||||
queryMutex->Unlock();
|
||||
this->ProcessQueryCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
queryMutex->Unlock();
|
||||
ke::AutoLock lock(&queryLock);
|
||||
if (Database == NULL)
|
||||
{
|
||||
cachedQueries.push_back(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cachedQueries.empty())
|
||||
this->ProcessQueryCache();
|
||||
}
|
||||
|
||||
query->SetDatabase(Database);
|
||||
@@ -348,12 +342,11 @@ bool ClientPrefs::AddQueryToQueue( TQueryOp *query )
|
||||
|
||||
void ClientPrefs::ProcessQueryCache()
|
||||
{
|
||||
if (Database == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
queryLock.AssertCurrentThreadOwns();
|
||||
|
||||
if (Database == NULL)
|
||||
return;
|
||||
|
||||
queryMutex->Lock();
|
||||
TQueryOp *op;
|
||||
for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end(); iter++)
|
||||
{
|
||||
@@ -363,7 +356,6 @@ void ClientPrefs::ProcessQueryCache()
|
||||
}
|
||||
|
||||
cachedQueries.clear();
|
||||
queryMutex->Unlock();
|
||||
}
|
||||
|
||||
size_t IsAuthIdConnected(char *authID)
|
||||
@@ -417,8 +409,7 @@ void ClientPrefs::CatchLateLoadClients()
|
||||
|
||||
void ClientPrefs::ClearQueryCache(int serial)
|
||||
{
|
||||
queryMutex->Lock();
|
||||
|
||||
ke::AutoLock lock(&queryLock);
|
||||
for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end();)
|
||||
{
|
||||
TQueryOp *op = *iter;
|
||||
@@ -432,7 +423,6 @@ void ClientPrefs::ClearQueryCache(int serial)
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
queryMutex->Unlock();
|
||||
}
|
||||
|
||||
bool Translate(char *buffer,
|
||||
@@ -530,7 +520,5 @@ ClientPrefs::ClientPrefs()
|
||||
phrases = NULL;
|
||||
DBInfo = NULL;
|
||||
|
||||
cookieMutex = NULL;
|
||||
queryMutex = NULL;
|
||||
identity = NULL;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod Client Preferences Extension
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -39,6 +39,8 @@
|
||||
#include "smsdk_ext.h"
|
||||
#include "sh_list.h"
|
||||
|
||||
#include <ke_thread_utils.h>
|
||||
|
||||
char * UTIL_strncpy(char * destination, const char * source, size_t num);
|
||||
|
||||
#include "cookie.h"
|
||||
@@ -73,11 +75,8 @@ public:
|
||||
* @return True to succeed loading, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief This is called right before the extension is unloaded.
|
||||
*/
|
||||
virtual void SDK_OnUnload();
|
||||
|
||||
virtual void SDK_OnDependenciesDropped();
|
||||
|
||||
/**
|
||||
* @brief This is called once all known extensions have been loaded.
|
||||
@@ -162,7 +161,7 @@ public:
|
||||
|
||||
private:
|
||||
SourceHook::List<TQueryOp *> cachedQueries;
|
||||
IMutex *queryMutex;
|
||||
ke::Mutex queryLock;
|
||||
IdentityToken_t *identity;
|
||||
};
|
||||
|
||||
|
||||
@@ -303,23 +303,6 @@ int TQueryOp::PullQuerySerial()
|
||||
|
||||
ParamData::~ParamData()
|
||||
{
|
||||
if (cookie)
|
||||
{
|
||||
g_ClientPrefs.cookieMutex->Lock();
|
||||
cookie->usedInQuery--;
|
||||
|
||||
if (cookie->shouldDelete && cookie->usedInQuery <= 0)
|
||||
{
|
||||
g_ClientPrefs.cookieMutex->Unlock();
|
||||
delete cookie;
|
||||
cookie = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ClientPrefs.cookieMutex->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if (data)
|
||||
{
|
||||
/* Data is only ever passed in a client disconnect query and always needs to be deleted */
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
//#define SMEXT_ENABLE_MEMUTILS
|
||||
#define SMEXT_ENABLE_GAMEHELPERS
|
||||
//#define SMEXT_ENABLE_TIMERSYS
|
||||
#define SMEXT_ENABLE_THREADER
|
||||
//#define SMEXT_ENABLE_THREADER
|
||||
//#define SMEXT_ENABLE_LIBSYS
|
||||
#define SMEXT_ENABLE_MENUS
|
||||
//#define SMEXT_ENABLE_ADTFACTORY
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod Base Extension Code
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -97,6 +97,12 @@ IUserMessages *usermsgs = NULL;
|
||||
#if defined SMEXT_ENABLE_TRANSLATOR
|
||||
ITranslator *translator = NULL;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_NINVOKE
|
||||
INativeInterface *ninvoke = NULL;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
|
||||
IRootConsole *rootconsole = NULL;
|
||||
#endif
|
||||
|
||||
/** Exports the main interface */
|
||||
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
|
||||
@@ -185,6 +191,12 @@ bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error,
|
||||
#if defined SMEXT_ENABLE_TRANSLATOR
|
||||
SM_GET_IFACE(TRANSLATOR, translator);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_NINVOKE
|
||||
SM_GET_IFACE(NINVOKE, ninvoke);
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
|
||||
SM_GET_IFACE(ROOTCONSOLE, rootconsole);
|
||||
#endif
|
||||
|
||||
if (SDK_OnLoad(error, maxlength, late))
|
||||
{
|
||||
@@ -227,6 +239,11 @@ void SDKExtension::OnExtensionUnload()
|
||||
SDK_OnUnload();
|
||||
}
|
||||
|
||||
void SDKExtension::OnDependenciesDropped()
|
||||
{
|
||||
SDK_OnDependenciesDropped();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionAuthor()
|
||||
{
|
||||
return SMEXT_CONF_AUTHOR;
|
||||
@@ -279,6 +296,10 @@ void SDKExtension::SDK_OnAllLoaded()
|
||||
{
|
||||
}
|
||||
|
||||
void SDKExtension::SDK_OnDependenciesDropped()
|
||||
{
|
||||
}
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
|
||||
PluginId g_PLID = 0; /**< Metamod plugin ID */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod Base Extension Code
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -91,6 +91,12 @@
|
||||
#if defined SMEXT_ENABLE_TRANSLATOR
|
||||
#include <ITranslator.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_NINVOKE
|
||||
#include <INativeInvoker.h>
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
|
||||
#include <IRootConsoleMenu.h>
|
||||
#endif
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
#include <ISmmPlugin.h>
|
||||
@@ -121,7 +127,7 @@ public:
|
||||
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
|
||||
|
||||
/**
|
||||
* @brief This is called right before the extension is unloaded.
|
||||
* @brief This is called once the extension unloading process begins.
|
||||
*/
|
||||
virtual void SDK_OnUnload();
|
||||
|
||||
@@ -135,6 +141,12 @@ public:
|
||||
*/
|
||||
virtual void SDK_OnPauseChange(bool paused);
|
||||
|
||||
/**
|
||||
* @brief Called after SDK_OnUnload, once all dependencies have been
|
||||
* removed, and the extension is about to be removed from memory.
|
||||
*/
|
||||
virtual void SDK_OnDependenciesDropped();
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
/**
|
||||
* @brief Called when Metamod is attached, before the extension version is called.
|
||||
@@ -197,6 +209,9 @@ public: //IExtensionInterface
|
||||
virtual const char *GetExtensionDescription();
|
||||
/** Returns date string */
|
||||
virtual const char *GetExtensionDateString();
|
||||
|
||||
/** Called after OnExtensionUnload, once dependencies have been dropped. */
|
||||
virtual void OnDependenciesDropped();
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
public: //ISmmPlugin
|
||||
/** Called when the extension is attached to Metamod. */
|
||||
@@ -289,6 +304,12 @@ extern IUserMessages *usermsgs;
|
||||
#if defined SMEXT_ENABLE_TRANSLATOR
|
||||
extern ITranslator *translator;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_NINVOKE
|
||||
extern INativeInterface *ninvoke;
|
||||
#endif
|
||||
#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
|
||||
extern IRootConsole *rootconsole;
|
||||
#endif
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
PLUGIN_GLOBALVARS();
|
||||
|
||||
Reference in New Issue
Block a user