Skip to content

Commit

Permalink
Gracefully shutdown metamod and plugins when game is closing (for a p…
Browse files Browse the repository at this point in the history
…roper reload using _restart command)
  • Loading branch information
s1lentq committed Nov 28, 2023
1 parent adc9414 commit ec926a6
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 14 deletions.
7 changes: 5 additions & 2 deletions metamod/src/dllapi.cpp
Expand Up @@ -12,8 +12,11 @@ NEW_DLL_FUNCTIONS sNewFunctionTable;
NEW_DLL_FUNCTIONS sNewFunctionTable_jit;
NEW_DLL_FUNCTIONS *pHookedNewDllFunctions = &sNewFunctionTable;

void MM_PRE_HOOK EXT_FUNC mm_GameShutdown()
// Unload game DLL and meta plugins
void MM_POST_HOOK EXT_FUNC mm_GameShutdown()
{
g_metamod_active = false;
if (g_plugins) g_plugins->unload_all();
g_meta_extdll.unload();
g_GameDLL.sys_module.unload();
g_engine.sys_module.unload();
Expand Down Expand Up @@ -130,7 +133,7 @@ compile_data_t g_dllfunc_cdata[] =
compile_data_t g_newdllfunc_cdata[] =
{
CDATA_NEWDLL(pfnOnFreeEntPrivateData), // Called right before the object's memory is freed. Calls its destructor.
CDATA_NEWDLL_H(pfnGameShutdown, P_PRE, mm_GameShutdown), //
CDATA_NEWDLL_H(pfnGameShutdown, P_POST, mm_GameShutdown), //
CDATA_NEWDLL(pfnShouldCollide), //

CDATA_NEWDLL(pfnCvarValue), // (fz) Use mm_CvarValue2 instead
Expand Down
6 changes: 6 additions & 0 deletions metamod/src/metamod.cpp
Expand Up @@ -32,6 +32,8 @@ unsigned int g_CALL_API_count = 0;

int g_requestid_counter = 0;

bool g_metamod_active = false;

// Very first metamod function that's run.
// Do startup operations...
void metamod_startup()
Expand Down Expand Up @@ -61,6 +63,8 @@ void metamod_startup()
Sys_Error("Failure to init game DLL; exiting...");
}

g_metamod_active = true;

// Register various console commands and cvars.
// Can I do these here, rather than waiting for GameDLLInit() ?
// Looks like it works okay..
Expand Down Expand Up @@ -509,6 +513,8 @@ static void meta_apply_fix_data(std::vector<fixdata_t>& data)

void meta_rebuild_callbacks()
{
if (!g_metamod_active) return;

std::vector<fixdata_t> fixdata;
if (g_metaGlobals.esp_save) {
META_LOG("dll: Begin scan to collect callback fix data...");
Expand Down
2 changes: 2 additions & 0 deletions metamod/src/metamod.h
Expand Up @@ -74,6 +74,8 @@ extern unsigned int g_CALL_API_count;
// stores previous requestid counter
extern int g_requestid_counter;

extern bool g_metamod_active;

// (patch by BAILOPAN)
// Holds cached player info, right now only things for querying cvars
// Max players is always 32, small enough that we can use a static array
Expand Down
9 changes: 9 additions & 0 deletions metamod/src/mlist.cpp
Expand Up @@ -573,6 +573,15 @@ void MPluginList::unpause_all()
}
}

// Unload all plugins currently loaded
void MPluginList::unload_all()
{
bool delayed;
for (auto p : m_plugins) {
p->unload(PT_ANYTIME, PNL_CMD_FORCED, delayed);
}
}

// Retry any pending actions on plugins, for instance load/unload delayed
// until changelevel.
void MPluginList::retry_all(PLUG_LOADTIME now)
Expand Down
1 change: 1 addition & 0 deletions metamod/src/mlist.h
Expand Up @@ -35,6 +35,7 @@ class MPluginList
bool load(); // load the list, at startup
bool refresh(PLUG_LOADTIME now); // update from re-read inifile
void unpause_all(); // unpause any paused plugins
void unload_all(); // unload all plugins
void retry_all(PLUG_LOADTIME now); // retry any pending plugin actions
void show(int source_index = 0); // list plugins to console use dynamic alignment
void show_static(int source_index = 0); // list plugins to console use static alignment
Expand Down
2 changes: 1 addition & 1 deletion metamod/src/mplugin.cpp
Expand Up @@ -471,7 +471,7 @@ bool MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, bool& delayed)
return false;
}
}
if (m_action != PA_UNLOAD && m_action != PA_RELOAD) {
if (m_action != PA_UNLOAD && m_action != PA_RELOAD && reason != PNL_CMD_FORCED) {
META_WARNING("dll: Not unloading plugin '%s'; not marked for unload (action=%s)", m_desc, str_action());
return false;
}
Expand Down
31 changes: 20 additions & 11 deletions metamod/src/mreg.cpp
Expand Up @@ -64,35 +64,44 @@ MRegCmd* MRegCmdList::add(const char* addname, REG_CMD_FN cmd_handler, MPlugin*

void MRegCmdList::remove(char* cmd_name)
{
for (auto it = m_list.begin(), end = m_list.end(); it != end; ++it) {
for (auto it = m_list.begin(); it != m_list.end(); ) {
auto reg = *it;

if (!Q_stricmp(reg->m_name, cmd_name)) {
if (g_RehldsFuncs) {
g_RehldsFuncs->Cmd_RemoveCmd(cmd_name);
m_list.erase(it);
delete reg;
it = m_list.erase(it);
}
else {
reg->disable();
it++;
}
} else {
it++;
}
}
}

// Disable any functions belonging to the given plugin (by index id).
void MRegCmdList::remove(int owner_plugin_id)
{
for (auto it = m_list.begin(), end = m_list.end(); it != end; ++it) {
for (auto it = m_list.begin(); it != m_list.end(); ) {
auto reg = *it;

if (reg->m_plugid == owner_plugin_id) {
if (g_RehldsFuncs) {
g_RehldsFuncs->Cmd_RemoveCmd(reg->m_name);
m_list.erase(it);
}
else {
reg->disable();
}
if (reg->m_plugid != owner_plugin_id) {
it++;
continue;
}

if (g_RehldsFuncs) {
g_RehldsFuncs->Cmd_RemoveCmd(reg->m_name);
delete reg;
it = m_list.erase(it);
}
else {
reg->disable();
it++;
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions metamod/src/sys_module.cpp
Expand Up @@ -68,6 +68,7 @@ module_handle_t CSysModule::load(const char *filepath)
{
if (!m_handle) {
m_handle = LoadLibrary(filepath);
if (m_handle) m_free = true;

MODULEINFO module_info;
if (GetModuleInformation(GetCurrentProcess(), m_handle, &module_info, sizeof(module_info))) {
Expand Down Expand Up @@ -157,6 +158,7 @@ module_handle_t CSysModule::load(const char *filepath)
{
if (!m_handle) {
m_handle = dlopen(filepath, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
if (m_handle) m_free = true;

char buf[1024], dummy[1024], path[260];
Q_sprintf(buf, "/proc/%i/maps", getpid());
Expand Down

0 comments on commit ec926a6

Please sign in to comment.