summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/modules.h5
-rwxr-xr-xmake/unit-cc.pl4
-rw-r--r--src/modmanager_static.cpp116
3 files changed, 86 insertions, 39 deletions
diff --git a/include/modules.h b/include/modules.h
index 8b2452494..5a9cb90e2 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -1670,8 +1670,11 @@ struct AllModuleList {
};
#define MODULE_INIT(x) static Module* MK_ ## x() { return new x; } \
- static const AllModuleList PREP_ ## x(&MK_ ## x, #x);
+ static const AllModuleList PREP_ ## x(&MK_ ## x, MODNAMESTR);
+#define MODNAMESTR MODNAMESTR_FN_2(MODNAME)
+#define MODNAMESTR_FN_2(x) MODNAMESTR_FN_1(x)
+#define MODNAMESTR_FN_1(x) #x
#else
diff --git a/make/unit-cc.pl b/make/unit-cc.pl
index e64053b66..aefefa4ac 100755
--- a/make/unit-cc.pl
+++ b/make/unit-cc.pl
@@ -29,6 +29,10 @@ my $cflags = $ENV{CXXFLAGS};
$cflags =~ s/ -pedantic// if nopedantic($file);
$cflags .= ' ' . getcompilerflags($file);
+if ($file =~ m#(?:^|/)((?:m|cmd)_[^/. ]+)(?:\.cpp|/.*\.cpp)$#) {
+ $cflags .= ' -DMODNAME='.$1.'.so';
+}
+
my $flags;
if ($out =~ /\.so$/) {
$flags = join ' ', $cflags, $ENV{PICLDFLAGS}, getlinkerflags($file);
diff --git a/src/modmanager_static.cpp b/src/modmanager_static.cpp
index ee9dc2107..534dcdec0 100644
--- a/src/modmanager_static.cpp
+++ b/src/modmanager_static.cpp
@@ -1,9 +1,13 @@
+#define MODNAME AllModule
+
#include "inspircd.h"
+#include "exitcodes.h"
#ifdef PURE_STATIC
+typedef std::map<std::string, AllModuleList*> modmap;
static std::vector<AllCommandList::fn>* cmdlist = NULL;
-static std::vector<AllModuleList*>* modlist = NULL;
+static modmap* modlist = NULL;
AllCommandList::AllCommandList(fn cmd)
{
@@ -15,8 +19,8 @@ AllCommandList::AllCommandList(fn cmd)
AllModuleList::AllModuleList(AllModuleList::fn mod, const std::string& Name) : init(mod), name(Name)
{
if (!modlist)
- modlist = new std::vector<AllModuleList*>();
- modlist->push_back(this);
+ modlist = new modmap();
+ modlist->insert(std::make_pair(Name, this));
}
class AllModule : public Module
@@ -58,31 +62,54 @@ class AllModule : public Module
MODULE_INIT(AllModule)
-bool ModuleManager::Load(const std::string& name, bool)
+bool ModuleManager::Load(const std::string& name, bool defer)
{
- for(std::vector<AllModuleList*>::iterator i = modlist->begin(); i != modlist->end(); ++i)
+ modmap::iterator it = modlist->find(name);
+ if (it == modlist->end())
+ return false;
+ Module* mod = NULL;
+ try
{
- if ((**i).name == name)
+ mod = (*it->second->init)();
+ mod->ModuleSourceFile = name;
+ mod->ModuleDLLManager = NULL;
+ Modules[name] = mod;
+ if (defer)
{
- Module* c = NULL;
- try
- {
- c = (*(**i).init)();
- Modules[name] = c;
- c->init();
- FOREACH_MOD(I_OnLoadModule,OnLoadModule(c));
- return true;
- }
- catch (CoreException& modexcept)
- {
- if (c)
- DoSafeUnload(c);
- delete c;
- ServerInstance->Logs->Log("MODULE", DEFAULT, "Unable to load " + (**i).name + ": " + modexcept.GetReason());
- }
+ ServerInstance->Logs->Log("MODULE", DEFAULT,"New module introduced: %s", name.c_str());
+ return true;
+ }
+ else
+ {
+ mod->init();
}
}
- return false;
+ catch (CoreException& modexcept)
+ {
+ if (mod)
+ DoSafeUnload(mod);
+ ServerInstance->Logs->Log("MODULE", DEFAULT, "Unable to load " + name + ": " + modexcept.GetReason());
+ return false;
+ }
+ FOREACH_MOD(I_OnLoadModule,OnLoadModule(mod));
+ /* We give every module a chance to re-prioritize when we introduce a new one,
+ * not just the one thats loading, as the new module could affect the preference
+ * of others
+ */
+ for(int tries = 0; tries < 20; tries++)
+ {
+ prioritizationState = tries > 0 ? PRIO_STATE_LAST : PRIO_STATE_FIRST;
+ for (std::map<std::string, Module*>::iterator n = Modules.begin(); n != Modules.end(); ++n)
+ n->second->Prioritize();
+
+ if (prioritizationState == PRIO_STATE_LAST)
+ break;
+ if (tries == 19)
+ ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected while loading " + name);
+ }
+
+ ServerInstance->BuildISupport();
+ return true;
}
namespace {
@@ -134,24 +161,36 @@ void ModuleManager::Reload(Module* mod, HandlerBase1<void, bool>* callback)
void ModuleManager::LoadAll()
{
- ModCount = 0;
- for(std::vector<AllModuleList*>::iterator i = modlist->begin(); i != modlist->end(); ++i)
+ Load("AllModule", true);
+
+ ConfigTagList tags = ServerInstance->Config->ConfTags("module");
+ for(ConfigIter i = tags.first; i != tags.second; ++i)
{
- Module* c = NULL;
- try
+ ConfigTag* tag = i->second;
+ std::string name = tag->getString("name");
+ printf_c("[\033[1;32m*\033[0m] Loading module:\t\033[1;32m%s\033[0m\n",name.c_str());
+
+ if (!this->Load(name, true))
+ {
+ ServerInstance->Logs->Log("MODULE", DEFAULT, this->LastError());
+ printf_c("\n[\033[1;31m*\033[0m] %s\n\n", this->LastError().c_str());
+ ServerInstance->Exit(EXIT_STATUS_MODULE);
+ }
+ }
+
+ for(std::map<std::string, Module*>::iterator i = Modules.begin(); i != Modules.end(); i++)
+ {
+ Module* mod = i->second;
+ try
{
- c = (*(**i).init)();
- c->ModuleSourceFile = (**i).name;
- c->ModuleDLLManager = NULL;
- Modules[(**i).name] = c;
- c->init();
+ mod->init();
}
catch (CoreException& modexcept)
{
- if (c)
- DoSafeUnload(c);
- delete c;
- ServerInstance->Logs->Log("MODULE", DEFAULT, "Unable to load " + (**i).name + ": " + modexcept.GetReason());
+ LastModuleError = "Unable to initialize " + mod->ModuleSourceFile + ": " + modexcept.GetReason();
+ ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError);
+ printf_c("\n[\033[1;31m*\033[0m] %s\n\n", LastModuleError.c_str());
+ ServerInstance->Exit(EXIT_STATUS_MODULE);
}
}
@@ -168,10 +207,11 @@ void ModuleManager::LoadAll()
if (prioritizationState == PRIO_STATE_LAST)
break;
if (tries == 19)
+ {
ServerInstance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected");
+ ServerInstance->Exit(EXIT_STATUS_MODULE);
+ }
}
-
- ServerInstance->BuildISupport();
}
void ModuleManager::UnloadAll()