fixed a dep bug

fixed a plugin unload iterator bug
extension unloading now works

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40316
This commit is contained in:
David Anderson 2007-01-18 09:14:20 +00:00
parent 1efdacd69b
commit 4ac5297d11
4 changed files with 147 additions and 5 deletions

View File

@ -5,6 +5,7 @@
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "PluginSys.h" #include "PluginSys.h"
#include "sm_srvcmds.h" #include "sm_srvcmds.h"
#include <stdlib.h>
CExtensionManager g_Extensions; CExtensionManager g_Extensions;
IdentityType_t g_ExtType; IdentityType_t g_ExtType;
@ -15,6 +16,7 @@ CExtension::CExtension(const char *filename, char *error, size_t err_max)
m_pAPI = NULL; m_pAPI = NULL;
m_pIdentToken = NULL; m_pIdentToken = NULL;
m_PlId = 0; m_PlId = 0;
unload_code = 0;
char path[PLATFORM_MAX_PATH+1]; char path[PLATFORM_MAX_PATH+1];
g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename); g_LibSys.PathFormat(path, PLATFORM_MAX_PATH, "%s/extensions/%s", g_SourceMod.GetSMBaseDir(), filename);
@ -349,6 +351,27 @@ void CExtensionManager::OnPluginDestroyed(IPlugin *plugin)
} }
} }
CExtension *CExtensionManager::FindByOrder(unsigned int num)
{
if (num < 1 || num > m_Libs.size())
{
return NULL;
}
List<CExtension *>::iterator iter = m_Libs.begin();
while (iter != m_Libs.end())
{
if (--num == 0)
{
return (*iter);
}
iter++;
}
return NULL;
}
bool CExtensionManager::UnloadExtension(IExtension *_pExt) bool CExtensionManager::UnloadExtension(IExtension *_pExt)
{ {
if (!_pExt) if (!_pExt)
@ -376,9 +399,9 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
List<IPlugin *>::iterator p_iter = pExt->m_Plugins.begin(); List<IPlugin *>::iterator p_iter = pExt->m_Plugins.begin();
while (p_iter != pExt->m_Plugins.end()) while (p_iter != pExt->m_Plugins.end())
{ {
/* We have to manually unlink ourselves here, since we're no longer being managed */
g_PluginSys.UnloadPlugin((*p_iter)); g_PluginSys.UnloadPlugin((*p_iter));
/* It should already have been removed! */ p_iter = pExt->m_Plugins.erase(p_iter);
assert(pExt->m_Plugins.find((*p_iter)) != pExt->m_Plugins.end());
} }
/* Notify and/or unload all dependencies */ /* Notify and/or unload all dependencies */
@ -392,6 +415,10 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt)
{ {
continue; continue;
} }
if (pDep == pExt)
{
continue;
}
/* Now, get its dependency list */ /* Now, get its dependency list */
bool dropped = false; bool dropped = false;
List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin(); List<IfaceInfo>::iterator i_iter = pDep->m_Deps.begin();
@ -524,10 +551,122 @@ void CExtensionManager::OnRootConsoleCommand(const char *cmd, unsigned int argco
g_RootMenu.ConsolePrint(" Metamod enabled: %s", pAPI->IsMetamodExtension() ? "yes" : "no"); g_RootMenu.ConsolePrint(" Metamod enabled: %s", pAPI->IsMetamodExtension() ? "yes" : "no");
} }
return; return;
} else if (strcmp(cmd, "unload") == 0) {
if (argcount < 4)
{
g_RootMenu.ConsolePrint("[SM] Usage: sm unload <#> [code]");
return;
}
const char *arg = g_RootMenu.GetArgument(3);
unsigned int num = atoi(arg);
CExtension *pExt = FindByOrder(num);
if (!pExt)
{
g_RootMenu.ConsolePrint("[SM] Extension number %d was not found.", num);
return;
}
if (argcount > 4 && pExt->unload_code)
{
const char *unload = g_RootMenu.GetArgument(4);
if (pExt->unload_code == atoi(unload))
{
char filename[PLATFORM_MAX_PATH+1];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
UnloadExtension(pExt);
g_RootMenu.ConsolePrint("[SM] Extension %s is now unloaded.", filename);
} else {
g_RootMenu.ConsolePrint("[SM] Please try again, the correct unload code is \"%d\"", pExt->unload_code);
}
return;
}
if (!pExt->IsLoaded()
|| (!pExt->m_Deps.size() && !pExt->m_Plugins.size()))
{
char filename[PLATFORM_MAX_PATH+1];
snprintf(filename, PLATFORM_MAX_PATH, "%s", pExt->GetFilename());
UnloadExtension(pExt);
g_RootMenu.ConsolePrint("[SM] Extension %s is now unloaded.", filename);
return;
} else {
List<IPlugin *> plugins;
if (pExt->m_Deps.size())
{
g_RootMenu.ConsolePrint("[SM] Unloading %s will unload the following extensions: ", pExt->GetFilename());
List<CExtension *>::iterator iter;
CExtension *pOther;
/* Get list of all extensions */
for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++)
{
List<IfaceInfo>::iterator i_iter;
pOther = (*iter);
if (!pOther->IsLoaded() || pOther == pExt)
{
continue;
}
/* Get their dependencies */
for (i_iter=pOther->m_Deps.begin();
i_iter!=pOther->m_Deps.end();
i_iter++)
{
/* Is this dependency to us? */
if ((*i_iter).owner != pExt)
{
continue;
}
/* Will our dependent care? */
if (!pExt->GetAPI()->QueryInterfaceDrop((*i_iter).iface))
{
g_RootMenu.ConsolePrint(" -> %s", pExt->GetFilename());
/* Add to plugin unload list */
List<IPlugin *>::iterator p_iter;
for (p_iter=pOther->m_Plugins.begin();
p_iter!=pOther->m_Plugins.end();
p_iter++)
{
if (plugins.find((*p_iter)) == plugins.end())
{
plugins.push_back((*p_iter));
}
}
}
}
}
}
if (pExt->m_Plugins.size())
{
g_RootMenu.ConsolePrint("[SM] Unloading %s will unload the following plugins: ", pExt->GetFilename());
List<IPlugin *>::iterator iter;
IPlugin *pPlugin;
for (iter = pExt->m_Plugins.begin(); iter != pExt->m_Plugins.end(); iter++)
{
pPlugin = (*iter);
if (plugins.find(pPlugin) == plugins.end())
{
plugins.push_back(pPlugin);
}
}
for (iter = plugins.begin(); iter != plugins.end(); iter++)
{
pPlugin = (*iter);
g_RootMenu.ConsolePrint(" -> %s", pPlugin->GetFilename());
}
}
srand(static_cast<int>(time(NULL)));
pExt->unload_code = (rand() % 877) + 123; //123 to 999
g_RootMenu.ConsolePrint("[SM] To verify unloading %s, please use the following: ", pExt->GetFilename());
g_RootMenu.ConsolePrint("[SM] sm exts unload %d %d", num, pExt->unload_code);
return;
}
} }
} }
g_RootMenu.ConsolePrint("SourceMod Extensions Menu:"); g_RootMenu.ConsolePrint("SourceMod Extensions Menu:");
g_RootMenu.DrawGenericOption("info", "Extra extension information"); g_RootMenu.DrawGenericOption("info", "Extra extension information");
g_RootMenu.DrawGenericOption("list", "List extensions"); g_RootMenu.DrawGenericOption("list", "List extensions");
g_RootMenu.DrawGenericOption("unload", "Unload an extension");
} }

View File

@ -44,6 +44,7 @@ private:
List<SMInterface *> m_Interfaces; List<SMInterface *> m_Interfaces;
List<IPlugin *> m_Plugins; List<IPlugin *> m_Plugins;
PluginId m_PlId; PluginId m_PlId;
unsigned int unload_code;
}; };
class CExtensionManager : class CExtensionManager :
@ -72,6 +73,8 @@ public:
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo); void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
void AddInterface(IExtension *pOwner, SMInterface *pInterface); void AddInterface(IExtension *pOwner, SMInterface *pInterface);
void BindChildPlugin(IExtension *pParent, IPlugin *pPlugin); void BindChildPlugin(IExtension *pParent, IPlugin *pPlugin);
private:
CExtension *FindByOrder(unsigned int num);
private: private:
List<CExtension *> m_Libs; List<CExtension *> m_Libs;
}; };

View File

@ -966,7 +966,7 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin)
List<IPluginsListener *>::iterator iter; List<IPluginsListener *>::iterator iter;
IPluginsListener *pListener; IPluginsListener *pListener;
if (pPlugin->GetStatus() >= Plugin_Error) if (pPlugin->GetStatus() <= Plugin_Error)
{ {
/* Notify listeners of unloading */ /* Notify listeners of unloading */
for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++) for (iter=m_listeners.begin(); iter!=m_listeners.end(); iter++)

View File

@ -113,7 +113,7 @@ bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface)
bool ShareSystem::RequestInterface(const char *iface_name, bool ShareSystem::RequestInterface(const char *iface_name,
unsigned int iface_vers, unsigned int iface_vers,
IExtension *mysql, IExtension *myself,
SMInterface **pIface) SMInterface **pIface)
{ {
/* See if the interface exists */ /* See if the interface exists */
@ -148,7 +148,7 @@ bool ShareSystem::RequestInterface(const char *iface_name,
IfaceInfo info; IfaceInfo info;
info.iface = iface; info.iface = iface;
info.owner = iface_owner; info.owner = iface_owner;
g_Extensions.BindDependency(iface_owner, &info); g_Extensions.BindDependency(myself, &info);
} }
if (pIface) if (pIface)