diff options
-rw-r--r-- | include/modules.h | 5 | ||||
-rw-r--r-- | src/modules.cpp | 27 |
2 files changed, 27 insertions, 5 deletions
diff --git a/include/modules.h b/include/modules.h index d26741a20..a539f3185 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1651,6 +1651,11 @@ class CoreExport ModuleManager : public classbase */ std::map<std::string, std::pair<ircd_module*, Module*> > Modules; + enum { + PRIO_STATE_FIRST, + PRIO_STATE_AGAIN, + PRIO_STATE_LAST + } prioritizationState; public: /** Event handler hooks. diff --git a/src/modules.cpp b/src/modules.cpp index 87e2de705..66134e3bc 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -288,11 +288,16 @@ bool ModuleManager::SetPriority(Module* mod, Implementation i, Priority s, Modul break; /* Module wants to be first, sod everything else */ case PRIORITY_FIRST: - swap_pos = 0; + if (prioritizationState != PRIO_STATE_FIRST) + swap = false; + else + swap_pos = 0; break; - /* Module is submissive and wants to be last... awww. */ + /* Module wants to be last. */ case PRIORITY_LAST: - if (EventHandlers[i].empty()) + if (prioritizationState != PRIO_STATE_FIRST) + swap = false; + else if (EventHandlers[i].empty()) swap_pos = 0; else swap_pos = EventHandlers[i].size() - 1; @@ -339,6 +344,9 @@ bool ModuleManager::SetPriority(Module* mod, Implementation i, Priority s, Modul /* Do we need to swap? */ if (swap && (swap_pos != source)) { + // We are going to change positions; we'll need to run again to verify all requirements + if (prioritizationState == PRIO_STATE_LAST) + prioritizationState = PRIO_STATE_AGAIN; /* Suggestion from Phoenix, "shuffle" the modules to better retain call order */ int incrmnt = 1; @@ -492,8 +500,17 @@ bool ModuleManager::Load(const char* filename) * not just the one thats loading, as the new module could affect the preference * of others */ - for (std::map<std::string, std::pair<ircd_module*, Module*> >::iterator n = Modules.begin(); n != Modules.end(); ++n) - n->second.second->Prioritize(); + for(int tries = 0; tries < 20; tries++) + { + prioritizationState = tries > 0 ? PRIO_STATE_LAST : PRIO_STATE_FIRST; + for (std::map<std::string, std::pair<ircd_module*, Module*> >::iterator n = Modules.begin(); n != Modules.end(); ++n) + n->second.second->Prioritize(); + + if (prioritizationState == PRIO_STATE_LAST) + break; + if (tries == 19) + Instance->Logs->Log("MODULE", DEFAULT, "Hook priority dependency loop detected while loading " + filename_str); + } Instance->BuildISupport(); return true; |