From c849616003d2b645e706468578c7f312c88f652a Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 1 Nov 2015 00:30:37 -0700 Subject: [PATCH] Add an OnPluginWillUnload callback that precedes OnPluginEnd(). --- core/logic/PluginSys.cpp | 8 ++++++++ public/IPluginSys.h | 20 +++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index 2e6d0fa9..dd5d3f46 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -1476,6 +1476,14 @@ void CPluginManager::Purge(CPlugin *plugin) // Go through our libraries and tell other plugins they're gone. plugin->LibraryActions(LibraryAction_Removed); + // Notify listeners of unloading. + if (plugin->EnteredSecondPass()) { + for (ListenerIter iter(m_listeners); !iter.done(); iter.next()) { + if ((*iter)->GetApiVersion() >= kMinPluginSysApiWithWillUnloadCallback) + (*iter)->OnPluginWillUnload(plugin); + } + } + // We only pair OnPluginEnd with OnPluginStart if we would have // successfully called OnPluginStart, *and* SetFailState() wasn't called, // which guarantees no further code will execute. diff --git a/public/IPluginSys.h b/public/IPluginSys.h index 85aaea3d..03c48878 100644 --- a/public/IPluginSys.h +++ b/public/IPluginSys.h @@ -38,7 +38,7 @@ #include #define SMINTERFACE_PLUGINSYSTEM_NAME "IPluginManager" -#define SMINTERFACE_PLUGINSYSTEM_VERSION 7 +#define SMINTERFACE_PLUGINSYSTEM_VERSION 8 /** Context user slot 3 is used Core for holding an IPluginContext pointer. */ #define SM_CONTEXTVAR_USER 3 @@ -304,6 +304,11 @@ namespace SourceMod // any plugin for which OnPluginLoaded was called, and is invoked // immediately after OnPluginEnd(). The plugin may be in any state Failed // or lower. + // + // This function must not cause the plugin to re-enter script code. If + // you wish to be notified of when a plugin is unloading, and to forbid + // future calls on that plugin, use OnPluginWillUnload and use a + // plugin property to block future calls. virtual void OnPluginUnloaded(IPlugin *plugin) { } @@ -322,8 +327,21 @@ namespace SourceMod virtual unsigned int GetApiVersion() const { return SMINTERFACE_PLUGINSYSTEM_VERSION; } + + // @brief Called when a plugin is about to be unloaded, before its + // OnPluginEnd callback is fired. This can be used to ensure that any + // asynchronous operations are flushed and no further operations can + // be started (via SetProperty). + // + // Like OnPluginUnloaded, this is only called for plugins which + // OnPluginLoaded was called. + virtual void OnPluginWillUnload(IPlugin *plugin) + { + } }; + static const unsigned int kMinPluginSysApiWithWillUnloadCallback = 8; + /** * @brief Manages the runtime loading and unloading of plugins. */