From 88b9ecb6b34d268f0761e6e961408871b6e91376 Mon Sep 17 00:00:00 2001 From: danieldg Date: Sun, 17 Jan 2010 03:17:25 +0000 Subject: PURE_STATIC improvements: Allow modules to be reloaded, generate linker arguments git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@12276 e03df62e-2008-0410-955e-edbf42e46eb7 --- make/calcdep.pl | 14 +++++++-- make/unit-cc.pl | 36 +++++++++++++++++++++++ src/modmanager_dynamic.cpp | 73 ---------------------------------------------- src/modmanager_static.cpp | 50 ++++++++++++++++++++++++------- src/modules.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 160 insertions(+), 86 deletions(-) diff --git a/make/calcdep.pl b/make/calcdep.pl index 1a1963b31..55e0630fc 100755 --- a/make/calcdep.pl +++ b/make/calcdep.pl @@ -120,20 +120,28 @@ bad-target: all: inspircd END - my @deps; + my(@deps, @srcs); for my $file (<*.cpp>, , , , , , "threadengines/threadengine_pthread.cpp") { my $out = find_output $file, 1; + if ($out =~ m#obj/([^/]+)/[^/]+.o$#) { + mkdir "$ENV{BUILDPATH}/obj/$1"; + } dep_cpp $file, $out; next if $file =~ m#^socketengines/# && $file ne "socketengines/$ENV{SOCKETENGINE}.cpp"; push @deps, $out; + push @srcs, $file; } my $core_mk = join ' ', @deps; + my $core_src = join ' ', @srcs; print MAKE < +obj/ld-extra.cmd: $core_src + \@\$(SOURCEPATH)/make/unit-cc.pl -f\$(VERBOSE) \$\@ \$^ \$> + +bin/inspircd: obj/ld-extra.cmd $core_mk + \@\$(SOURCEPATH)/make/unit-cc.pl -l\$(VERBOSE) \$\@ \$^ \$> inspircd: bin/inspircd diff --git a/make/unit-cc.pl b/make/unit-cc.pl index 23a7dfb76..489b46ff9 100755 --- a/make/unit-cc.pl +++ b/make/unit-cc.pl @@ -13,6 +13,14 @@ if ($out =~ /^-/) { $_ = $out; $out = shift; $verbose = /v/; + if (/f/) { + do_static_find(@ARGV); + exit; + } + if (/l/) { + do_static_link(@ARGV); + exit; + } } my $file = shift; @@ -32,3 +40,31 @@ my $execstr = "$ENV{RUNCC} $flags -o $out $file"; print "$execstr\n" if $verbose; exec $execstr; exit 1; + +sub do_static_find { + my @flags; + for my $file (@ARGV) { + push @flags, getlinkerflags($file); + } + open F, '>', $out; + print F join ' ', @flags; + close F; +} + +sub do_static_link { + my $execstr = "$ENV{RUNCC} -o $out $ENV{CORELDFLAGS} $ENV{LDLIBS}"; + for (@ARGV) { + if (/\.cmd$/) { + open F, '<', $_; + my $libs = ; + chomp $libs; + $execstr .= ' '.$libs; + close F; + } else { + $execstr .= ' '.$_; + } + } + print "$execstr\n" if $verbose; + exec $execstr; + exit 1; +} diff --git a/src/modmanager_dynamic.cpp b/src/modmanager_dynamic.cpp index 2f686ec96..900562260 100644 --- a/src/modmanager_dynamic.cpp +++ b/src/modmanager_dynamic.cpp @@ -136,79 +136,6 @@ bool ModuleManager::Load(const char* filename) return true; } -bool ModuleManager::CanUnload(Module* mod) -{ - std::map::iterator modfind = Modules.find(mod->ModuleSourceFile); - - if (modfind == Modules.end() || modfind->second != mod) - { - LastModuleError = "Module " + mod->ModuleSourceFile + " is not loaded, cannot unload it!"; - ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError); - return false; - } - if (mod->GetVersion().Flags & VF_STATIC) - { - LastModuleError = "Module " + mod->ModuleSourceFile + " not unloadable (marked static)"; - ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError); - return false; - } - return true; -} - -void ModuleManager::DoSafeUnload(Module* mod) -{ - std::map::iterator modfind = Modules.find(mod->ModuleSourceFile); - - std::vector > items; - ServerInstance->Extensions.BeginUnregister(modfind->second, items); - /* Give the module a chance to tidy out all its metadata */ - for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++) - { - mod->OnCleanup(TYPE_CHANNEL,c->second); - c->second->doUnhookExtensions(items); - const UserMembList* users = c->second->GetUsers(); - for(UserMembCIter mi = users->begin(); mi != users->end(); mi++) - mi->second->doUnhookExtensions(items); - } - for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); u++) - { - mod->OnCleanup(TYPE_USER,u->second); - u->second->doUnhookExtensions(items); - } - for(char m='A'; m <= 'z'; m++) - { - ModeHandler* mh; - mh = ServerInstance->Modes->FindMode(m, MODETYPE_USER); - if (mh && mh->creator == mod) - ServerInstance->Modes->DelMode(mh); - mh = ServerInstance->Modes->FindMode(m, MODETYPE_CHANNEL); - if (mh && mh->creator == mod) - ServerInstance->Modes->DelMode(mh); - } - for(std::multimap::iterator i = DataProviders.begin(); i != DataProviders.end(); ) - { - std::multimap::iterator curr = i++; - if (curr->second->creator == mod) - DataProviders.erase(curr); - } - for(unsigned int i = 0; i < ServerInstance->Modules->ActiveDynrefs.size(); i++) - ServerInstance->Modules->ActiveDynrefs[i]->ClearCache(); - - /* Tidy up any dangling resolvers */ - ServerInstance->Res->CleanResolvers(mod); - - FOREACH_MOD(I_OnUnloadModule,OnUnloadModule(mod)); - - DetachAll(mod); - - Modules.erase(modfind); - ServerInstance->GlobalCulls.AddItem(mod); - - ServerInstance->Logs->Log("MODULE", DEFAULT,"Module %s unloaded",mod->ModuleSourceFile.c_str()); - this->ModCount--; - ServerInstance->BuildISupport(); -} - namespace { struct UnloadAction : public HandlerBase0 { diff --git a/src/modmanager_static.cpp b/src/modmanager_static.cpp index e09310a13..322703679 100644 --- a/src/modmanager_static.cpp +++ b/src/modmanager_static.cpp @@ -58,28 +58,58 @@ class AllModule : public Module MODULE_INIT(AllModule) -bool ModuleManager::Load(const char* filename) +bool ModuleManager::Load(const char* name) { + for(std::vector::iterator i = modlist->begin(); i != modlist->end(); ++i) + { + if ((**i).name == name) + { + try + { + Module* c = (*(**i).init)(); + Modules[name] = c; + FOREACH_MOD(I_OnLoadModule,OnLoadModule(c)); + return true; + } + catch (CoreException& modexcept) + { + ServerInstance->Logs->Log("MODULE", DEFAULT, "Unable to load " + (**i).name + ": " + modexcept.GetReason()); + } + } + } return false; } -bool ModuleManager::CanUnload(Module* mod) +bool ModuleManager::Unload(Module* mod) { return false; } -void ModuleManager::DoSafeUnload(Module* mod) -{ -} - -bool ModuleManager::Unload(Module* mod) -{ - return false; +namespace { + struct ReloadAction : public HandlerBase0 + { + Module* const mod; + HandlerBase1* const callback; + ReloadAction(Module* m, HandlerBase1* c) + : mod(m), callback(c) {} + void Call() + { + std::string name = mod->ModuleSourceFile; + ServerInstance->Modules->DoSafeUnload(mod); + ServerInstance->GlobalCulls.Apply(); + bool rv = ServerInstance->Modules->Load(name.c_str()); + callback->Call(rv); + ServerInstance->GlobalCulls.AddItem(this); + } + }; } void ModuleManager::Reload(Module* mod, HandlerBase1* callback) { - callback->Call(false); + if (CanUnload(mod)) + ServerInstance->AtomicActions.AddAction(new ReloadAction(mod, callback)); + else + callback->Call(false); } void ModuleManager::LoadAll() diff --git a/src/modules.cpp b/src/modules.cpp index cbd6c7b38..b25469c30 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -329,6 +329,79 @@ bool ModuleManager::SetPriority(Module* mod, Implementation i, Priority s, Modul return true; } +bool ModuleManager::CanUnload(Module* mod) +{ + std::map::iterator modfind = Modules.find(mod->ModuleSourceFile); + + if (modfind == Modules.end() || modfind->second != mod) + { + LastModuleError = "Module " + mod->ModuleSourceFile + " is not loaded, cannot unload it!"; + ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError); + return false; + } + if (mod->GetVersion().Flags & VF_STATIC) + { + LastModuleError = "Module " + mod->ModuleSourceFile + " not unloadable (marked static)"; + ServerInstance->Logs->Log("MODULE", DEFAULT, LastModuleError); + return false; + } + return true; +} + +void ModuleManager::DoSafeUnload(Module* mod) +{ + std::map::iterator modfind = Modules.find(mod->ModuleSourceFile); + + std::vector > items; + ServerInstance->Extensions.BeginUnregister(modfind->second, items); + /* Give the module a chance to tidy out all its metadata */ + for (chan_hash::iterator c = ServerInstance->chanlist->begin(); c != ServerInstance->chanlist->end(); c++) + { + mod->OnCleanup(TYPE_CHANNEL,c->second); + c->second->doUnhookExtensions(items); + const UserMembList* users = c->second->GetUsers(); + for(UserMembCIter mi = users->begin(); mi != users->end(); mi++) + mi->second->doUnhookExtensions(items); + } + for (user_hash::iterator u = ServerInstance->Users->clientlist->begin(); u != ServerInstance->Users->clientlist->end(); u++) + { + mod->OnCleanup(TYPE_USER,u->second); + u->second->doUnhookExtensions(items); + } + for(char m='A'; m <= 'z'; m++) + { + ModeHandler* mh; + mh = ServerInstance->Modes->FindMode(m, MODETYPE_USER); + if (mh && mh->creator == mod) + ServerInstance->Modes->DelMode(mh); + mh = ServerInstance->Modes->FindMode(m, MODETYPE_CHANNEL); + if (mh && mh->creator == mod) + ServerInstance->Modes->DelMode(mh); + } + for(std::multimap::iterator i = DataProviders.begin(); i != DataProviders.end(); ) + { + std::multimap::iterator curr = i++; + if (curr->second->creator == mod) + DataProviders.erase(curr); + } + for(unsigned int i = 0; i < ServerInstance->Modules->ActiveDynrefs.size(); i++) + ServerInstance->Modules->ActiveDynrefs[i]->ClearCache(); + + /* Tidy up any dangling resolvers */ + ServerInstance->Res->CleanResolvers(mod); + + FOREACH_MOD(I_OnUnloadModule,OnUnloadModule(mod)); + + DetachAll(mod); + + Modules.erase(modfind); + ServerInstance->GlobalCulls.AddItem(mod); + + ServerInstance->Logs->Log("MODULE", DEFAULT,"Module %s unloaded",mod->ModuleSourceFile.c_str()); + this->ModCount--; + ServerInstance->BuildISupport(); +} + std::string& ModuleManager::LastError() { return LastModuleError; -- cgit v1.2.3