Fix various problems with unloading ClientPrefs and SourceMod (bug 5874, r=ds).
--HG-- extra : rebase_source : 0a35f8380d651ca65fac9dd402c5cd3625e3105c
This commit is contained in:
+10
-17
@@ -775,25 +775,21 @@ CExtension *CExtensionManager::FindByOrder(unsigned int num)
|
||||
bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
||||
{
|
||||
if (!_pExt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CExtension *pExt = (CExtension *)_pExt;
|
||||
|
||||
if (m_Libs.find(pExt) == m_Libs.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Tell it to unload */
|
||||
if (pExt->IsLoaded())
|
||||
{
|
||||
IExtensionInterface *pAPI = pExt->GetAPI();
|
||||
pAPI->OnExtensionUnload();
|
||||
}
|
||||
pExt->GetAPI()->OnExtensionUnload();
|
||||
|
||||
/* First remove us from internal lists */
|
||||
// Remove us from internal lists. Note that because we do this, it's
|
||||
// possible that our extension could be added back if another plugin
|
||||
// tries to load during this process. If we ever find this to happen,
|
||||
// we can just block plugin loading.
|
||||
g_ShareSys.RemoveInterfaces(_pExt);
|
||||
m_Libs.remove(pExt);
|
||||
|
||||
@@ -827,13 +823,9 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
||||
{
|
||||
pDep = (*c_iter);
|
||||
if ((pAPI=pDep->GetAPI()) == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pDep == pExt)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* Now, get its dependency list */
|
||||
bool dropped = false;
|
||||
List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin();
|
||||
@@ -862,13 +854,9 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
||||
while (i_iter != pDep->m_ChildDeps.end())
|
||||
{
|
||||
if ((*i_iter).owner == pExt)
|
||||
{
|
||||
i_iter = pDep->m_ChildDeps.erase(i_iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
i_iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,6 +875,11 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
|
||||
}
|
||||
}
|
||||
|
||||
// Everything has been informed that we're unloading, so give the
|
||||
// extension one last notification.
|
||||
if (pExt->IsLoaded() && pExt->GetAPI()->GetExtensionVersion() >= 7)
|
||||
pExt->GetAPI()->OnDependenciesDropped();
|
||||
|
||||
pExt->Unload();
|
||||
delete pExt;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
@@ -147,6 +147,7 @@ static void logic_init(const sm_core_t* core, sm_logic_t* _logic)
|
||||
gamehelpers = core->gamehelpers;
|
||||
g_pSourcePawn = *core->spe1;
|
||||
g_pSourcePawn2 = *core->spe2;
|
||||
SMGlobalClass::head = core->listeners;
|
||||
|
||||
g_ShareSys.Initialize();
|
||||
g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
|
||||
|
||||
@@ -49,7 +49,7 @@ using namespace SourceHook;
|
||||
* Add 1 to the RHS of this expression to bump the intercom file
|
||||
* This is to prevent mismatching core/logic binaries
|
||||
*/
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 22)
|
||||
#define SM_LOGIC_MAGIC (0x0F47C0DE - 23)
|
||||
|
||||
#if defined SM_LOGIC
|
||||
class IVEngineServer
|
||||
@@ -270,6 +270,7 @@ struct sm_core_t
|
||||
void * serverFactory;
|
||||
void * engineFactory;
|
||||
void * matchmakingDSFactory;
|
||||
SMGlobalClass * listeners;
|
||||
};
|
||||
|
||||
struct sm_logic_t
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 sw=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
@@ -406,6 +406,7 @@ void InitLogicBridge()
|
||||
|
||||
core_bridge.engineFactory = (void *)g_SMAPI->GetEngineFactory(false);
|
||||
core_bridge.serverFactory = (void *)g_SMAPI->GetServerFactory(false);
|
||||
core_bridge.listeners = SMGlobalClass::head;
|
||||
|
||||
ILibrary *mmlib;
|
||||
char path[PLATFORM_MAX_PATH];
|
||||
|
||||
+61
-52
@@ -129,6 +129,8 @@ ConfigResult SourceModBase::OnSourceModConfigChanged(const char *key,
|
||||
return ConfigResult_Ignore;
|
||||
}
|
||||
|
||||
static bool sSourceModInitialized = false;
|
||||
|
||||
bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late)
|
||||
{
|
||||
const char *gamepath = g_SMAPI->GetBaseDir();
|
||||
@@ -240,6 +242,8 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t maxlength, bool late
|
||||
|
||||
g_pSourcePawn2->SetDebugListener(logicore.debugger);
|
||||
|
||||
sSourceModInitialized = true;
|
||||
|
||||
/* Hook this now so we can detect startup without calling StartSourceMod() */
|
||||
SH_ADD_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SourceModBase::LevelInit), false);
|
||||
|
||||
@@ -475,69 +479,74 @@ size_t SourceModBase::BuildPath(PathType type, char *buffer, size_t maxlength, c
|
||||
|
||||
void SourceModBase::CloseSourceMod()
|
||||
{
|
||||
/* Force a level end */
|
||||
LevelShutdown();
|
||||
if (!sSourceModInitialized)
|
||||
return;
|
||||
|
||||
SH_REMOVE_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SourceModBase::LevelInit), false);
|
||||
|
||||
if (g_Loaded)
|
||||
{
|
||||
/* Force a level end */
|
||||
LevelShutdown();
|
||||
ShutdownServices();
|
||||
}
|
||||
|
||||
/* Rest In Peace */
|
||||
ShutdownLogicBridge();
|
||||
ShutdownJIT();
|
||||
}
|
||||
|
||||
void SourceModBase::ShutdownServices()
|
||||
{
|
||||
/* Unload plugins */
|
||||
scripts->Shutdown();
|
||||
|
||||
/* Unload extensions */
|
||||
extsys->Shutdown();
|
||||
|
||||
SH_REMOVE_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(this, &SourceModBase::LevelInit), false);
|
||||
if (g_pOnMapEnd)
|
||||
g_Forwards.ReleaseForward(g_pOnMapEnd);
|
||||
|
||||
if (g_Loaded)
|
||||
/* Notify! */
|
||||
SMGlobalClass *pBase = SMGlobalClass::head;
|
||||
while (pBase)
|
||||
{
|
||||
if (g_pOnMapEnd)
|
||||
{
|
||||
g_Forwards.ReleaseForward(g_pOnMapEnd);
|
||||
}
|
||||
|
||||
/* Notify! */
|
||||
SMGlobalClass *pBase = SMGlobalClass::head;
|
||||
while (pBase)
|
||||
{
|
||||
pBase->OnSourceModShutdown();
|
||||
pBase = pBase->m_pGlobalClassNext;
|
||||
}
|
||||
|
||||
/* Delete all data packs */
|
||||
CStack<CDataPack *>::iterator iter;
|
||||
CDataPack *pd;
|
||||
for (iter=m_freepacks.begin(); iter!=m_freepacks.end(); iter++)
|
||||
{
|
||||
pd = (*iter);
|
||||
delete pd;
|
||||
}
|
||||
m_freepacks.popall();
|
||||
|
||||
/* Notify! */
|
||||
pBase = SMGlobalClass::head;
|
||||
while (pBase)
|
||||
{
|
||||
pBase->OnSourceModAllShutdown();
|
||||
pBase = pBase->m_pGlobalClassNext;
|
||||
}
|
||||
|
||||
if (enginePatch)
|
||||
{
|
||||
SH_RELEASE_CALLCLASS(enginePatch);
|
||||
enginePatch = NULL;
|
||||
}
|
||||
|
||||
if (gamedllPatch)
|
||||
{
|
||||
SH_RELEASE_CALLCLASS(gamedllPatch);
|
||||
gamedllPatch = NULL;
|
||||
}
|
||||
|
||||
SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SourceModBase::LevelShutdown), false);
|
||||
SH_REMOVE_HOOK(IServerGameDLL, GameFrame, gamedll, SH_MEMBER(&g_Timers, &TimerSystem::GameFrame), false);
|
||||
pBase->OnSourceModShutdown();
|
||||
pBase = pBase->m_pGlobalClassNext;
|
||||
}
|
||||
|
||||
/* Rest In Peace */
|
||||
ShutdownLogicBridge();
|
||||
ShutdownJIT();
|
||||
/* Delete all data packs */
|
||||
CStack<CDataPack *>::iterator iter;
|
||||
CDataPack *pd;
|
||||
for (iter=m_freepacks.begin(); iter!=m_freepacks.end(); iter++)
|
||||
{
|
||||
pd = (*iter);
|
||||
delete pd;
|
||||
}
|
||||
m_freepacks.popall();
|
||||
|
||||
/* Notify! */
|
||||
pBase = SMGlobalClass::head;
|
||||
while (pBase)
|
||||
{
|
||||
pBase->OnSourceModAllShutdown();
|
||||
pBase = pBase->m_pGlobalClassNext;
|
||||
}
|
||||
|
||||
if (enginePatch)
|
||||
{
|
||||
SH_RELEASE_CALLCLASS(enginePatch);
|
||||
enginePatch = NULL;
|
||||
}
|
||||
|
||||
if (gamedllPatch)
|
||||
{
|
||||
SH_RELEASE_CALLCLASS(gamedllPatch);
|
||||
gamedllPatch = NULL;
|
||||
}
|
||||
|
||||
SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &SourceModBase::LevelShutdown), false);
|
||||
SH_REMOVE_HOOK(IServerGameDLL, GameFrame, gamedll, SH_MEMBER(&g_Timers, &TimerSystem::GameFrame), false);
|
||||
}
|
||||
|
||||
void SourceModBase::LogMessage(IExtension *pExt, const char *format, ...)
|
||||
|
||||
+3
-1
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* vim: set ts=4 sw=4 tw=99 noet:
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved.
|
||||
@@ -136,6 +136,8 @@ public: // ISourceMod
|
||||
int GetPluginId();
|
||||
int GetShApiVersion();
|
||||
bool IsMapRunning();
|
||||
private:
|
||||
void ShutdownServices();
|
||||
private:
|
||||
CStack<CDataPack *> m_freepacks;
|
||||
char m_SMBaseDir[PLATFORM_MAX_PATH];
|
||||
|
||||
Reference in New Issue
Block a user