mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2025-03-21 12:28:56 +01:00
Now unloading the original gamedll in DLLShutdown() instead of using a __attribute__((destructor)) function
-> Also auto-removing ConCommandBases with the FCVAR_GAMEDLL flag before doing that --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40115
This commit is contained in:
parent
e242aa662d
commit
18bfaa7021
@ -84,6 +84,37 @@ void SMConVarAccessor::Unregister(ConCommandBase *pCommand)
|
||||
}
|
||||
}
|
||||
|
||||
void SMConVarAccessor::UnregisterGameDLLCommands()
|
||||
{
|
||||
ConCommandBase *begin = g_Engine.icvar->GetCommands();
|
||||
ConCommandBase *iter = begin;
|
||||
ConCommandBase *prev = NULL;
|
||||
while (iter)
|
||||
{
|
||||
// watch out for the ETERNAL COMMAND!
|
||||
if (iter != &g_EternalCommand && iter->IsBitSet(FCVAR_GAMEDLL))
|
||||
{
|
||||
// Remove it!
|
||||
if (iter == begin)
|
||||
{
|
||||
g_EternalCommand.BringToFront();
|
||||
iter = const_cast<ConCommandBase*>(iter->GetNext());
|
||||
g_EternalCommand.SetNext(iter);
|
||||
prev = &g_EternalCommand;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter = const_cast<ConCommandBase*>(iter->GetNext());
|
||||
prev->SetNext(iter);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
prev = iter;
|
||||
iter = const_cast<ConCommandBase*>(iter->GetNext());
|
||||
}
|
||||
}
|
||||
|
||||
ConVar metamod_version("metamod_version", SOURCEMM_VERSION, FCVAR_REPLICATED | FCVAR_SPONLY | FCVAR_NOTIFY, "Metamod:Source Version");
|
||||
#if defined WIN32 || defined _WIN32
|
||||
ConVar mm_pluginsfile("mm_pluginsfile", "addons\\metamod\\metaplugins.ini", FCVAR_SPONLY, "Metamod:Source Plugins File");
|
||||
|
@ -30,6 +30,7 @@ public:
|
||||
bool Register(ConCommandBase *pCommand);
|
||||
void MarkCommandsAsGameDLL();
|
||||
void Unregister(ConCommandBase *pCommand);
|
||||
void UnregisterGameDLLCommands();
|
||||
};
|
||||
|
||||
class CAlwaysRegisterableCommand : public ConCommandBase
|
||||
|
@ -37,7 +37,6 @@ SourceHook::ISourceHook *g_SHPtr;
|
||||
SourceHook::String g_ModPath;
|
||||
SourceHook::String g_BinPath;
|
||||
PluginId g_PLID = Pl_Console; //Technically, SourceMM is the "Console" plugin... :p
|
||||
bool bInShutdown = false;
|
||||
bool bInFirstLevel = true;
|
||||
|
||||
///////////////////////////////////
|
||||
@ -268,44 +267,21 @@ void Shutdown()
|
||||
g_SMConVarAccessor.MarkCommandsAsGameDLL();
|
||||
}
|
||||
|
||||
// The engine uses the DLL even after it has call DLLShutdown, so we unload it
|
||||
// when it unloads us
|
||||
#if defined _WIN32
|
||||
BOOL WINAPI DllMain(
|
||||
HINSTANCE hinstDLL,
|
||||
DWORD fdwReason,
|
||||
LPVOID lpvReserved
|
||||
)
|
||||
{
|
||||
if (fdwReason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
if (!bInShutdown)
|
||||
Shutdown();
|
||||
if (g_GameDll.lib && g_GameDll.loaded)
|
||||
dlclose(g_GameDll.lib);
|
||||
memset(&g_GameDll, 0, sizeof(GameDllInfo));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#elif defined __linux__
|
||||
void __attribute__ ((destructor)) app_fini(void)
|
||||
{
|
||||
if (!bInShutdown)
|
||||
Shutdown();
|
||||
if (g_GameDll.lib && g_GameDll.loaded)
|
||||
dlclose(g_GameDll.lib);
|
||||
memset(&g_GameDll, 0, sizeof(GameDllInfo));
|
||||
}
|
||||
#endif
|
||||
|
||||
void CServerGameDLL::DLLShutdown()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
//Call the original function
|
||||
//Call the original function
|
||||
m_pOrig->DLLShutdown();
|
||||
|
||||
bInShutdown = true;
|
||||
//Unregister all commands marked as GameDLL now
|
||||
//This prevents crashes when the engine tries to unregister them once we have already unloaded the gamedll
|
||||
//(we used to unload the gamedll in a __attribute__((destructor)) function but I've had problems with that (crashes in dlclose)
|
||||
g_SMConVarAccessor.UnregisterGameDLLCommands();
|
||||
|
||||
if (g_GameDll.lib && g_GameDll.loaded)
|
||||
dlclose(g_GameDll.lib);
|
||||
memset(&g_GameDll, 0, sizeof(GameDllInfo));
|
||||
}
|
||||
|
||||
int LoadPluginsFromFile(const char *file)
|
||||
|
Loading…
x
Reference in New Issue
Block a user