Fix various problems with unloading ClientPrefs and SourceMod (bug 5874, r=ds).
1.1 --- a/core/logic/ExtensionSys.cpp Wed Aug 21 10:55:12 2013 -0400
1.2 +++ b/core/logic/ExtensionSys.cpp Thu Aug 22 14:05:44 2013 -0700
1.3 @@ -775,25 +775,21 @@
1.4 bool CExtensionManager::UnloadExtension(IExtension *_pExt)
1.5 {
1.6 if (!_pExt)
1.7 - {
1.8 return false;
1.9 - }
1.10
1.11 CExtension *pExt = (CExtension *)_pExt;
1.12
1.13 if (m_Libs.find(pExt) == m_Libs.end())
1.14 - {
1.15 return false;
1.16 - }
1.17
1.18 /* Tell it to unload */
1.19 if (pExt->IsLoaded())
1.20 - {
1.21 - IExtensionInterface *pAPI = pExt->GetAPI();
1.22 - pAPI->OnExtensionUnload();
1.23 - }
1.24 + pExt->GetAPI()->OnExtensionUnload();
1.25
1.26 - /* First remove us from internal lists */
1.27 + // Remove us from internal lists. Note that because we do this, it's
1.28 + // possible that our extension could be added back if another plugin
1.29 + // tries to load during this process. If we ever find this to happen,
1.30 + // we can just block plugin loading.
1.31 g_ShareSys.RemoveInterfaces(_pExt);
1.32 m_Libs.remove(pExt);
1.33
1.34 @@ -827,13 +823,9 @@
1.35 {
1.36 pDep = (*c_iter);
1.37 if ((pAPI=pDep->GetAPI()) == NULL)
1.38 - {
1.39 continue;
1.40 - }
1.41 if (pDep == pExt)
1.42 - {
1.43 continue;
1.44 - }
1.45 /* Now, get its dependency list */
1.46 bool dropped = false;
1.47 List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin();
1.48 @@ -862,13 +854,9 @@
1.49 while (i_iter != pDep->m_ChildDeps.end())
1.50 {
1.51 if ((*i_iter).owner == pExt)
1.52 - {
1.53 i_iter = pDep->m_ChildDeps.erase(i_iter);
1.54 - }
1.55 else
1.56 - {
1.57 i_iter++;
1.58 - }
1.59 }
1.60 }
1.61
1.62 @@ -887,6 +875,11 @@
1.63 }
1.64 }
1.65
1.66 + // Everything has been informed that we're unloading, so give the
1.67 + // extension one last notification.
1.68 + if (pExt->IsLoaded() && pExt->GetAPI()->GetExtensionVersion() >= 7)
1.69 + pExt->GetAPI()->OnDependenciesDropped();
1.70 +
1.71 pExt->Unload();
1.72 delete pExt;
1.73
2.1 --- a/core/logic/common_logic.cpp Wed Aug 21 10:55:12 2013 -0400
2.2 +++ b/core/logic/common_logic.cpp Thu Aug 22 14:05:44 2013 -0700
2.3 @@ -1,5 +1,5 @@
2.4 /**
2.5 - * vim: set ts=4 sw=4 :
2.6 + * vim: set ts=4 sw=4 tw=99 noet:
2.7 * =============================================================================
2.8 * SourceMod
2.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
2.10 @@ -147,6 +147,7 @@
2.11 gamehelpers = core->gamehelpers;
2.12 g_pSourcePawn = *core->spe1;
2.13 g_pSourcePawn2 = *core->spe2;
2.14 + SMGlobalClass::head = core->listeners;
2.15
2.16 g_ShareSys.Initialize();
2.17 g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
3.1 --- a/core/logic/intercom.h Wed Aug 21 10:55:12 2013 -0400
3.2 +++ b/core/logic/intercom.h Thu Aug 22 14:05:44 2013 -0700
3.3 @@ -49,7 +49,7 @@
3.4 * Add 1 to the RHS of this expression to bump the intercom file
3.5 * This is to prevent mismatching core/logic binaries
3.6 */
3.7 -#define SM_LOGIC_MAGIC (0x0F47C0DE - 22)
3.8 +#define SM_LOGIC_MAGIC (0x0F47C0DE - 23)
3.9
3.10 #if defined SM_LOGIC
3.11 class IVEngineServer
3.12 @@ -270,6 +270,7 @@
3.13 void * serverFactory;
3.14 void * engineFactory;
3.15 void * matchmakingDSFactory;
3.16 + SMGlobalClass * listeners;
3.17 };
3.18
3.19 struct sm_logic_t
4.1 --- a/core/logic_bridge.cpp Wed Aug 21 10:55:12 2013 -0400
4.2 +++ b/core/logic_bridge.cpp Thu Aug 22 14:05:44 2013 -0700
4.3 @@ -1,5 +1,5 @@
4.4 /**
4.5 - * vim: set ts=4 sw=4 :
4.6 + * vim: set ts=4 sw=4 tw=99 noet:
4.7 * =============================================================================
4.8 * SourceMod
4.9 * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
4.10 @@ -406,6 +406,7 @@
4.11
4.12 core_bridge.engineFactory = (void *)g_SMAPI->GetEngineFactory(false);
4.13 core_bridge.serverFactory = (void *)g_SMAPI->GetServerFactory(false);
4.14 + core_bridge.listeners = SMGlobalClass::head;
4.15
4.16 ILibrary *mmlib;
4.17 char path[PLATFORM_MAX_PATH];
5.1 --- a/core/sourcemod.cpp Wed Aug 21 10:55:12 2013 -0400
5.2 +++ b/core/sourcemod.cpp Thu Aug 22 14:05:44 2013 -0700
5.3 @@ -129,6 +129,8 @@
5.4 return ConfigResult_Ignore;
5.5 }
5.6
5.7 +static bool sSourceModInitialized = false;
5.8 +
5.9 bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late)
5.10 {
5.11 const char *gamepath = g_SMAPI->GetBaseDir();
5.12 @@ -240,6 +242,8 @@
5.13
5.14 g_pSourcePawn2->SetDebugListener(logicore.debugger);
5.15
5.16 + sSourceModInitialized = true;
5.17 +
5.18 /* Hook this now so we can detect startup without calling StartSourceMod() */
5.19 SH_ADD_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SourceModBase::LevelInit), false);
5.20
5.21 @@ -475,69 +479,74 @@
5.22
5.23 void SourceModBase::CloseSourceMod()
5.24 {
5.25 - /* Force a level end */
5.26 - LevelShutdown();
5.27 + if (!sSourceModInitialized)
5.28 + return;
5.29 +
5.30 + SH_REMOVE_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SourceModBase::LevelInit), false);
5.31
5.32 + if (g_Loaded)
5.33 + {
5.34 + /* Force a level end */
5.35 + LevelShutdown();
5.36 + ShutdownServices();
5.37 + }
5.38 +
5.39 + /* Rest In Peace */
5.40 + ShutdownLogicBridge();
5.41 + ShutdownJIT();
5.42 +}
5.43 +
5.44 +void SourceModBase::ShutdownServices()
5.45 +{
5.46 /* Unload plugins */
5.47 scripts->Shutdown();
5.48
5.49 /* Unload extensions */
5.50 extsys->Shutdown();
5.51
5.52 - SH_REMOVE_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SourceModBase::LevelInit), false);
5.53 + if (g_pOnMapEnd)
5.54 + g_Forwards.ReleaseForward(g_pOnMapEnd);
5.55
5.56 - if (g_Loaded)
5.57 + /* Notify! */
5.58 + SMGlobalClass *pBase = SMGlobalClass::head;
5.59 + while (pBase)
5.60 {
5.61 - if (g_pOnMapEnd)
5.62 - {
5.63 - g_Forwards.ReleaseForward(g_pOnMapEnd);
5.64 - }
5.65 -
5.66 - /* Notify! */
5.67 - SMGlobalClass *pBase = SMGlobalClass::head;
5.68 - while (pBase)
5.69 - {
5.70 - pBase->OnSourceModShutdown();
5.71 - pBase = pBase->m_pGlobalClassNext;
5.72 - }
5.73 -
5.74 - /* Delete all data packs */
5.75 - CStack<CDataPack *>::iterator iter;
5.76 - CDataPack *pd;
5.77 - for (iter=m_freepacks.begin(); iter!=m_freepacks.end(); iter++)
5.78 - {
5.79 - pd = (*iter);
5.80 - delete pd;
5.81 - }
5.82 - m_freepacks.popall();
5.83 -
5.84 - /* Notify! */
5.85 - pBase = SMGlobalClass::head;
5.86 - while (pBase)
5.87 - {
5.88 - pBase->OnSourceModAllShutdown();
5.89 - pBase = pBase->m_pGlobalClassNext;
5.90 - }
5.91 -
5.92 - if (enginePatch)
5.93 - {
5.94 - SH_RELEASE_CALLCLASS(enginePatch);
5.95 - enginePatch = NULL;
5.96 - }
5.97 -
5.98 - if (gamedllPatch)
5.99 - {
5.100 - SH_RELEASE_CALLCLASS(gamedllPatch);
5.101 - gamedllPatch = NULL;
5.102 - }
5.103 -
5.104 - SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SourceModBase::LevelShutdown), false);
5.105 - SH_REMOVE_HOOK(IServerGameDLL, GameFrame, gamedll, SH_MEMBER(&g_Timers, &TimerSystem::GameFrame), false);
5.106 + pBase->OnSourceModShutdown();
5.107 + pBase = pBase->m_pGlobalClassNext;
5.108 }
5.109
5.110 - /* Rest In Peace */
5.111 - ShutdownLogicBridge();
5.112 - ShutdownJIT();
5.113 + /* Delete all data packs */
5.114 + CStack<CDataPack *>::iterator iter;
5.115 + CDataPack *pd;
5.116 + for (iter=m_freepacks.begin(); iter!=m_freepacks.end(); iter++)
5.117 + {
5.118 + pd = (*iter);
5.119 + delete pd;
5.120 + }
5.121 + m_freepacks.popall();
5.122 +
5.123 + /* Notify! */
5.124 + pBase = SMGlobalClass::head;
5.125 + while (pBase)
5.126 + {
5.127 + pBase->OnSourceModAllShutdown();
5.128 + pBase = pBase->m_pGlobalClassNext;
5.129 + }
5.130 +
5.131 + if (enginePatch)
5.132 + {
5.133 + SH_RELEASE_CALLCLASS(enginePatch);
5.134 + enginePatch = NULL;
5.135 + }
5.136 +
5.137 + if (gamedllPatch)
5.138 + {
5.139 + SH_RELEASE_CALLCLASS(gamedllPatch);
5.140 + gamedllPatch = NULL;
5.141 + }
5.142 +
5.143 + SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SourceModBase::LevelShutdown), false);
5.144 + SH_REMOVE_HOOK(IServerGameDLL, GameFrame, gamedll, SH_MEMBER(&g_Timers, &TimerSystem::GameFrame), false);
5.145 }
5.146
5.147 void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
6.1 --- a/core/sourcemod.h Wed Aug 21 10:55:12 2013 -0400
6.2 +++ b/core/sourcemod.h Thu Aug 22 14:05:44 2013 -0700
6.3 @@ -1,5 +1,5 @@
6.4 /**
6.5 - * vim: set ts=4 :
6.6 + * vim: set ts=4 sw=4 tw=99 noet:
6.7 * =============================================================================
6.8 * SourceMod
6.9 * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
6.10 @@ -137,6 +137,8 @@
6.11 int GetShApiVersion();
6.12 bool IsMapRunning();
6.13 private:
6.14 + void ShutdownServices();
6.15 +private:
6.16 CStack<CDataPack *> m_freepacks;
6.17 char m_SMBaseDir[PLATFORM_MAX_PATH];
6.18 char m_SMRelDir[PLATFORM_MAX_PATH];
7.1 --- a/extensions/clientprefs/cookie.cpp Wed Aug 21 10:55:12 2013 -0400
7.2 +++ b/extensions/clientprefs/cookie.cpp Thu Aug 22 14:05:44 2013 -0700
7.3 @@ -1,5 +1,5 @@
7.4 /**
7.5 - * vim: set ts=4 :
7.6 + * vim: set ts=4 sw=4 tw=99 noet:
7.7 * =============================================================================
7.8 * SourceMod Client Preferences Extension
7.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
7.10 @@ -55,35 +55,12 @@
7.11 for (int i = playerhelpers->GetMaxClients()+1; --i > 0;)
7.12 {
7.13 if (connected[i])
7.14 - {
7.15 OnClientDisconnecting(i);
7.16 - }
7.17 }
7.18
7.19 /* Find all cookies and delete them */
7.20 - Cookie *current;
7.21 -
7.22 for (SourceHook::List<Cookie *>::iterator _iter = cookieList.begin(); _iter != cookieList.end(); _iter++)
7.23 - {
7.24 - current = (Cookie *)*_iter;
7.25 -
7.26 - if (current == NULL)
7.27 - {
7.28 - continue;
7.29 - }
7.30 -
7.31 - g_ClientPrefs.cookieMutex->Lock();
7.32 - if (current->usedInQuery)
7.33 - {
7.34 - current->shouldDelete = true;
7.35 - g_ClientPrefs.cookieMutex->Unlock();
7.36 - }
7.37 - else
7.38 - {
7.39 - g_ClientPrefs.cookieMutex->Unlock();
7.40 - delete current;
7.41 - }
7.42 - }
7.43 + delete (*_iter);
7.44
7.45 cookieList.clear();
7.46 }
7.47 @@ -93,9 +70,7 @@
7.48 Cookie **pCookie = cookieTrie.retrieve(name);
7.49
7.50 if (pCookie == NULL)
7.51 - {
7.52 return NULL;
7.53 - }
7.54
7.55 return *pCookie;
7.56 }
7.57 @@ -116,7 +91,6 @@
7.58
7.59 /* First time cookie - Create from scratch */
7.60 pCookie = new Cookie(name, description, access);
7.61 - pCookie->usedInQuery++;
7.62
7.63 /* Attempt to insert cookie into the db and get its ID num */
7.64 TQueryOp *op = new TQueryOp(Query_InsertCookie, pCookie);
8.1 --- a/extensions/clientprefs/cookie.h Wed Aug 21 10:55:12 2013 -0400
8.2 +++ b/extensions/clientprefs/cookie.h Thu Aug 22 14:05:44 2013 -0700
8.3 @@ -75,12 +75,7 @@
8.4 dbid = -1;
8.5
8.6 for (int i=0; i<=MAXCLIENTS; i++)
8.7 - {
8.8 data[i] = NULL;
8.9 - }
8.10 -
8.11 - shouldDelete = false;
8.12 - usedInQuery = 0;
8.13 }
8.14
8.15 ~Cookie()
8.16 @@ -88,9 +83,7 @@
8.17 for (int i=0; i<=MAXCLIENTS; i++)
8.18 {
8.19 if (data[i] != NULL)
8.20 - {
8.21 delete data[i];
8.22 - }
8.23 }
8.24 }
8.25
8.26 @@ -99,10 +92,6 @@
8.27 int dbid;
8.28 CookieData *data[MAXCLIENTS+1];
8.29 CookieAccess access;
8.30 -
8.31 - /* Reference counting stuff */
8.32 - bool shouldDelete;
8.33 - int usedInQuery;
8.34 };
8.35
8.36 class CookieManager : public IClientListener, public IPluginsListener
9.1 --- a/extensions/clientprefs/extension.cpp Wed Aug 21 10:55:12 2013 -0400
9.2 +++ b/extensions/clientprefs/extension.cpp Thu Aug 22 14:05:44 2013 -0700
9.3 @@ -1,5 +1,5 @@
9.4 /**
9.5 - * vim: set ts=4 :
9.6 + * vim: set ts=4 sw=4 tw=99 noet:
9.7 * =============================================================================
9.8 * SourceMod Client Preferences Extension
9.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
9.10 @@ -50,9 +50,6 @@
9.11
9.12 bool ClientPrefs::SDK_OnLoad(char *error, size_t maxlength, bool late)
9.13 {
9.14 - queryMutex = threader->MakeMutex();
9.15 - cookieMutex = threader->MakeMutex();
9.16 -
9.17 DBInfo = dbi->FindDatabaseConf("clientprefs");
9.18
9.19 if (DBInfo == NULL)
9.20 @@ -155,13 +152,15 @@
9.21 }
9.22 }
9.23
9.24 -void ClientPrefs::SDK_OnUnload()
9.25 +void ClientPrefs::SDK_OnDependenciesDropped()
9.26 {
9.27 + // At this point, we're guaranteed that DBI has flushed the worker thread
9.28 + // for us, so no cookies should have outstanding queries.
9.29 + g_CookieManager.Unload();
9.30 +
9.31 handlesys->RemoveType(g_CookieType, myself->GetIdentity());
9.32 handlesys->RemoveType(g_CookieIterator, myself->GetIdentity());
9.33
9.34 - g_CookieManager.Unload();
9.35 -
9.36 if (Database != NULL)
9.37 {
9.38 Database->Close();
9.39 @@ -199,9 +198,6 @@
9.40
9.41 plsys->RemovePluginsListener(&g_CookieManager);
9.42 playerhelpers->RemoveClientListener(&g_CookieManager);
9.43 -
9.44 - queryMutex->DestroyThis();
9.45 - cookieMutex->DestroyThis();
9.46 }
9.47
9.48 void ClientPrefs::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
9.49 @@ -312,7 +308,11 @@
9.50
9.51 databaseLoading = false;
9.52
9.53 - this->ProcessQueryCache();
9.54 + // Need a new scope because of the goto above.
9.55 + {
9.56 + ke::AutoLock lock(&queryLock);
9.57 + this->ProcessQueryCache();
9.58 + }
9.59 return;
9.60
9.61 fatal_fail:
9.62 @@ -321,24 +321,18 @@
9.63 databaseLoading = false;
9.64 }
9.65
9.66 -bool ClientPrefs::AddQueryToQueue( TQueryOp *query )
9.67 +bool ClientPrefs::AddQueryToQueue(TQueryOp *query)
9.68 {
9.69 - queryMutex->Lock();
9.70 - if (Database == NULL)
9.71 {
9.72 - cachedQueries.push_back(query);
9.73 - queryMutex->Unlock();
9.74 - return false;
9.75 - }
9.76 -
9.77 - if (!cachedQueries.empty())
9.78 - {
9.79 - queryMutex->Unlock();
9.80 - this->ProcessQueryCache();
9.81 - }
9.82 - else
9.83 - {
9.84 - queryMutex->Unlock();
9.85 + ke::AutoLock lock(&queryLock);
9.86 + if (Database == NULL)
9.87 + {
9.88 + cachedQueries.push_back(query);
9.89 + return false;
9.90 + }
9.91 +
9.92 + if (!cachedQueries.empty())
9.93 + this->ProcessQueryCache();
9.94 }
9.95
9.96 query->SetDatabase(Database);
9.97 @@ -348,12 +342,11 @@
9.98
9.99 void ClientPrefs::ProcessQueryCache()
9.100 {
9.101 + queryLock.AssertCurrentThreadOwns();
9.102 +
9.103 if (Database == NULL)
9.104 - {
9.105 return;
9.106 - }
9.107
9.108 - queryMutex->Lock();
9.109 TQueryOp *op;
9.110 for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end(); iter++)
9.111 {
9.112 @@ -363,7 +356,6 @@
9.113 }
9.114
9.115 cachedQueries.clear();
9.116 - queryMutex->Unlock();
9.117 }
9.118
9.119 size_t IsAuthIdConnected(char *authID)
9.120 @@ -417,8 +409,7 @@
9.121
9.122 void ClientPrefs::ClearQueryCache(int serial)
9.123 {
9.124 - queryMutex->Lock();
9.125 -
9.126 + ke::AutoLock lock(&queryLock);
9.127 for (SourceHook::List<TQueryOp *>::iterator iter = cachedQueries.begin(); iter != cachedQueries.end();)
9.128 {
9.129 TQueryOp *op = *iter;
9.130 @@ -432,7 +423,6 @@
9.131 iter++;
9.132 }
9.133 }
9.134 - queryMutex->Unlock();
9.135 }
9.136
9.137 bool Translate(char *buffer,
9.138 @@ -530,7 +520,5 @@
9.139 phrases = NULL;
9.140 DBInfo = NULL;
9.141
9.142 - cookieMutex = NULL;
9.143 - queryMutex = NULL;
9.144 identity = NULL;
9.145 }
10.1 --- a/extensions/clientprefs/extension.h Wed Aug 21 10:55:12 2013 -0400
10.2 +++ b/extensions/clientprefs/extension.h Thu Aug 22 14:05:44 2013 -0700
10.3 @@ -1,5 +1,5 @@
10.4 /**
10.5 - * vim: set ts=4 :
10.6 + * vim: set ts=4 sw=4 tw=99 noet:
10.7 * =============================================================================
10.8 * SourceMod Client Preferences Extension
10.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
10.10 @@ -39,6 +39,8 @@
10.11 #include "smsdk_ext.h"
10.12 #include "sh_list.h"
10.13
10.14 +#include <ke_thread_utils.h>
10.15 +
10.16 char * UTIL_strncpy(char * destination, const char * source, size_t num);
10.17
10.18 #include "cookie.h"
10.19 @@ -73,11 +75,8 @@
10.20 * @return True to succeed loading, false to fail.
10.21 */
10.22 virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
10.23 -
10.24 - /**
10.25 - * @brief This is called right before the extension is unloaded.
10.26 - */
10.27 - virtual void SDK_OnUnload();
10.28 +
10.29 + virtual void SDK_OnDependenciesDropped();
10.30
10.31 /**
10.32 * @brief This is called once all known extensions have been loaded.
10.33 @@ -162,7 +161,7 @@
10.34
10.35 private:
10.36 SourceHook::List<TQueryOp *> cachedQueries;
10.37 - IMutex *queryMutex;
10.38 + ke::Mutex queryLock;
10.39 IdentityToken_t *identity;
10.40 };
10.41
11.1 --- a/extensions/clientprefs/query.cpp Wed Aug 21 10:55:12 2013 -0400
11.2 +++ b/extensions/clientprefs/query.cpp Thu Aug 22 14:05:44 2013 -0700
11.3 @@ -303,23 +303,6 @@
11.4
11.5 ParamData::~ParamData()
11.6 {
11.7 - if (cookie)
11.8 - {
11.9 - g_ClientPrefs.cookieMutex->Lock();
11.10 - cookie->usedInQuery--;
11.11 -
11.12 - if (cookie->shouldDelete && cookie->usedInQuery <= 0)
11.13 - {
11.14 - g_ClientPrefs.cookieMutex->Unlock();
11.15 - delete cookie;
11.16 - cookie = NULL;
11.17 - }
11.18 - else
11.19 - {
11.20 - g_ClientPrefs.cookieMutex->Unlock();
11.21 - }
11.22 - }
11.23 -
11.24 if (data)
11.25 {
11.26 /* Data is only ever passed in a client disconnect query and always needs to be deleted */
12.1 --- a/extensions/clientprefs/sdk/smsdk_config.h Wed Aug 21 10:55:12 2013 -0400
12.2 +++ b/extensions/clientprefs/sdk/smsdk_config.h Thu Aug 22 14:05:44 2013 -0700
12.3 @@ -67,7 +67,7 @@
12.4 //#define SMEXT_ENABLE_MEMUTILS
12.5 #define SMEXT_ENABLE_GAMEHELPERS
12.6 //#define SMEXT_ENABLE_TIMERSYS
12.7 -#define SMEXT_ENABLE_THREADER
12.8 +//#define SMEXT_ENABLE_THREADER
12.9 //#define SMEXT_ENABLE_LIBSYS
12.10 #define SMEXT_ENABLE_MENUS
12.11 //#define SMEXT_ENABLE_ADTFACTORY
13.1 --- a/extensions/clientprefs/sdk/smsdk_ext.cpp Wed Aug 21 10:55:12 2013 -0400
13.2 +++ b/extensions/clientprefs/sdk/smsdk_ext.cpp Thu Aug 22 14:05:44 2013 -0700
13.3 @@ -1,5 +1,5 @@
13.4 /**
13.5 - * vim: set ts=4 :
13.6 + * vim: set ts=4 sw=4 tw=99 noet:
13.7 * =============================================================================
13.8 * SourceMod Base Extension Code
13.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
13.10 @@ -97,6 +97,12 @@
13.11 #if defined SMEXT_ENABLE_TRANSLATOR
13.12 ITranslator *translator = NULL;
13.13 #endif
13.14 +#if defined SMEXT_ENABLE_NINVOKE
13.15 +INativeInterface *ninvoke = NULL;
13.16 +#endif
13.17 +#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
13.18 +IRootConsole *rootconsole = NULL;
13.19 +#endif
13.20
13.21 /** Exports the main interface */
13.22 PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
13.23 @@ -185,6 +191,12 @@
13.24 #if defined SMEXT_ENABLE_TRANSLATOR
13.25 SM_GET_IFACE(TRANSLATOR, translator);
13.26 #endif
13.27 +#if defined SMEXT_ENABLE_NINVOKE
13.28 + SM_GET_IFACE(NINVOKE, ninvoke);
13.29 +#endif
13.30 +#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
13.31 + SM_GET_IFACE(ROOTCONSOLE, rootconsole);
13.32 +#endif
13.33
13.34 if (SDK_OnLoad(error, maxlength, late))
13.35 {
13.36 @@ -227,6 +239,11 @@
13.37 SDK_OnUnload();
13.38 }
13.39
13.40 +void SDKExtension::OnDependenciesDropped()
13.41 +{
13.42 + SDK_OnDependenciesDropped();
13.43 +}
13.44 +
13.45 const char *SDKExtension::GetExtensionAuthor()
13.46 {
13.47 return SMEXT_CONF_AUTHOR;
13.48 @@ -279,6 +296,10 @@
13.49 {
13.50 }
13.51
13.52 +void SDKExtension::SDK_OnDependenciesDropped()
13.53 +{
13.54 +}
13.55 +
13.56 #if defined SMEXT_CONF_METAMOD
13.57
13.58 PluginId g_PLID = 0; /**< Metamod plugin ID */
14.1 --- a/extensions/clientprefs/sdk/smsdk_ext.h Wed Aug 21 10:55:12 2013 -0400
14.2 +++ b/extensions/clientprefs/sdk/smsdk_ext.h Thu Aug 22 14:05:44 2013 -0700
14.3 @@ -1,5 +1,5 @@
14.4 /**
14.5 - * vim: set ts=4 :
14.6 + * vim: set ts=4 sw=4 tw=99 noet:
14.7 * =============================================================================
14.8 * SourceMod Base Extension Code
14.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
14.10 @@ -91,6 +91,12 @@
14.11 #if defined SMEXT_ENABLE_TRANSLATOR
14.12 #include <ITranslator.h>
14.13 #endif
14.14 +#if defined SMEXT_ENABLE_NINVOKE
14.15 +#include <INativeInvoker.h>
14.16 +#endif
14.17 +#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
14.18 +#include <IRootConsoleMenu.h>
14.19 +#endif
14.20
14.21 #if defined SMEXT_CONF_METAMOD
14.22 #include <ISmmPlugin.h>
14.23 @@ -121,7 +127,7 @@
14.24 virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
14.25
14.26 /**
14.27 - * @brief This is called right before the extension is unloaded.
14.28 + * @brief This is called once the extension unloading process begins.
14.29 */
14.30 virtual void SDK_OnUnload();
14.31
14.32 @@ -135,6 +141,12 @@
14.33 */
14.34 virtual void SDK_OnPauseChange(bool paused);
14.35
14.36 + /**
14.37 + * @brief Called after SDK_OnUnload, once all dependencies have been
14.38 + * removed, and the extension is about to be removed from memory.
14.39 + */
14.40 + virtual void SDK_OnDependenciesDropped();
14.41 +
14.42 #if defined SMEXT_CONF_METAMOD
14.43 /**
14.44 * @brief Called when Metamod is attached, before the extension version is called.
14.45 @@ -197,6 +209,9 @@
14.46 virtual const char *GetExtensionDescription();
14.47 /** Returns date string */
14.48 virtual const char *GetExtensionDateString();
14.49 +
14.50 + /** Called after OnExtensionUnload, once dependencies have been dropped. */
14.51 + virtual void OnDependenciesDropped();
14.52 #if defined SMEXT_CONF_METAMOD
14.53 public: //ISmmPlugin
14.54 /** Called when the extension is attached to Metamod. */
14.55 @@ -289,6 +304,12 @@
14.56 #if defined SMEXT_ENABLE_TRANSLATOR
14.57 extern ITranslator *translator;
14.58 #endif
14.59 +#if defined SMEXT_ENABLE_NINVOKE
14.60 +extern INativeInterface *ninvoke;
14.61 +#endif
14.62 +#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
14.63 +extern IRootConsole *rootconsole;
14.64 +#endif
14.65
14.66 #if defined SMEXT_CONF_METAMOD
14.67 PLUGIN_GLOBALVARS();
15.1 --- a/public/IExtensionSys.h Wed Aug 21 10:55:12 2013 -0400
15.2 +++ b/public/IExtensionSys.h Thu Aug 22 14:05:44 2013 -0700
15.3 @@ -1,5 +1,5 @@
15.4 /**
15.5 - * vim: set ts=4 :
15.6 + * vim: set ts=4 sw=4 tw=99 noet:
15.7 * =============================================================================
15.8 * SourceMod
15.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
15.10 @@ -134,8 +134,9 @@
15.11 * itself is not versioned.
15.12 *
15.13 * V6 - added TestFeature() to IShareSys.
15.14 + * V7 - added OnDependenciesDropped() to IExtensionInterface.
15.15 */
15.16 - #define SMINTERFACE_EXTENSIONAPI_VERSION 6
15.17 + #define SMINTERFACE_EXTENSIONAPI_VERSION 7
15.18
15.19 /**
15.20 * @brief The interface an extension must expose.
15.21 @@ -313,6 +314,17 @@
15.22 virtual void OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
15.23 {
15.24 }
15.25 +
15.26 + /**
15.27 + * @brief Called once all dependencies have been unloaded. This is
15.28 + * called AFTER OnExtensionUnload(), but before the extension library
15.29 + * has been unloaded. It can be used as an alternate unload hook for
15.30 + * cases where having no dependent plugins would make shutdown much
15.31 + * simplier.
15.32 + */
15.33 + virtual void OnDependenciesDropped()
15.34 + {
15.35 + }
15.36 };
15.37
15.38 /**
16.1 --- a/public/sample_ext/sdk/smsdk_ext.cpp Wed Aug 21 10:55:12 2013 -0400
16.2 +++ b/public/sample_ext/sdk/smsdk_ext.cpp Thu Aug 22 14:05:44 2013 -0700
16.3 @@ -1,5 +1,5 @@
16.4 /**
16.5 - * vim: set ts=4 :
16.6 + * vim: set ts=4 sw=4 tw=99 noet:
16.7 * =============================================================================
16.8 * SourceMod Base Extension Code
16.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
16.10 @@ -239,6 +239,11 @@
16.11 SDK_OnUnload();
16.12 }
16.13
16.14 +void SDKExtension::OnDependenciesDropped()
16.15 +{
16.16 + SDK_OnDependenciesDropped();
16.17 +}
16.18 +
16.19 const char *SDKExtension::GetExtensionAuthor()
16.20 {
16.21 return SMEXT_CONF_AUTHOR;
16.22 @@ -291,6 +296,10 @@
16.23 {
16.24 }
16.25
16.26 +void SDKExtension::SDK_OnDependenciesDropped()
16.27 +{
16.28 +}
16.29 +
16.30 #if defined SMEXT_CONF_METAMOD
16.31
16.32 PluginId g_PLID = 0; /**< Metamod plugin ID */
17.1 --- a/public/sample_ext/sdk/smsdk_ext.h Wed Aug 21 10:55:12 2013 -0400
17.2 +++ b/public/sample_ext/sdk/smsdk_ext.h Thu Aug 22 14:05:44 2013 -0700
17.3 @@ -1,5 +1,5 @@
17.4 /**
17.5 - * vim: set ts=4 :
17.6 + * vim: set ts=4 sw=4 tw=99 noet:
17.7 * =============================================================================
17.8 * SourceMod Base Extension Code
17.9 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
17.10 @@ -127,7 +127,7 @@
17.11 virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
17.12
17.13 /**
17.14 - * @brief This is called right before the extension is unloaded.
17.15 + * @brief This is called once the extension unloading process begins.
17.16 */
17.17 virtual void SDK_OnUnload();
17.18
17.19 @@ -141,6 +141,12 @@
17.20 */
17.21 virtual void SDK_OnPauseChange(bool paused);
17.22
17.23 + /**
17.24 + * @brief Called after SDK_OnUnload, once all dependencies have been
17.25 + * removed, and the extension is about to be removed from memory.
17.26 + */
17.27 + virtual void SDK_OnDependenciesDropped();
17.28 +
17.29 #if defined SMEXT_CONF_METAMOD
17.30 /**
17.31 * @brief Called when Metamod is attached, before the extension version is called.
17.32 @@ -203,6 +209,9 @@
17.33 virtual const char *GetExtensionDescription();
17.34 /** Returns date string */
17.35 virtual const char *GetExtensionDateString();
17.36 +
17.37 + /** Called after OnExtensionUnload, once dependencies have been dropped. */
17.38 + virtual void OnDependenciesDropped();
17.39 #if defined SMEXT_CONF_METAMOD
17.40 public: //ISmmPlugin
17.41 /** Called when the extension is attached to Metamod. */