mirror of
https://github.com/matrix-construct/construct
synced 2024-11-04 21:08:57 +01:00
ircd::mods: Add unloading state; add public interface for loading()/unloading() query.
This commit is contained in:
parent
5fa42b5afd
commit
15b300657f
3 changed files with 49 additions and 11 deletions
|
@ -46,6 +46,8 @@ namespace ircd::mods
|
||||||
namespace ircd::mods
|
namespace ircd::mods
|
||||||
{
|
{
|
||||||
bool loaded(const string_view &name);
|
bool loaded(const string_view &name);
|
||||||
|
bool loading(const string_view &name);
|
||||||
|
bool unloading(const string_view &name);
|
||||||
bool available(const string_view &name);
|
bool available(const string_view &name);
|
||||||
bool is_module(const string_view &fullpath);
|
bool is_module(const string_view &fullpath);
|
||||||
bool is_module(const string_view &fullpath, std::nothrow_t);
|
bool is_module(const string_view &fullpath, std::nothrow_t);
|
||||||
|
|
57
ircd/mods.cc
57
ircd/mods.cc
|
@ -191,6 +191,30 @@ ircd::mods::available(const string_view &name)
|
||||||
return !search(name, why).empty();
|
return !search(name, why).empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::mods::unloading(const string_view &name)
|
||||||
|
{
|
||||||
|
const auto &list(mod::unloading);
|
||||||
|
return end(list) != std::find_if(begin(list), end(list), [&name]
|
||||||
|
(const auto *const &mod)
|
||||||
|
{
|
||||||
|
assert(mod);
|
||||||
|
return mod->name() == name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::mods::loading(const string_view &name)
|
||||||
|
{
|
||||||
|
const auto &list(mod::loading);
|
||||||
|
return end(list) != std::find_if(begin(list), end(list), [&name]
|
||||||
|
(const auto *const &mod)
|
||||||
|
{
|
||||||
|
assert(mod);
|
||||||
|
return mod->name() == name;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::loaded(const string_view &name)
|
ircd::mods::loaded(const string_view &name)
|
||||||
{
|
{
|
||||||
|
@ -675,6 +699,10 @@ decltype(ircd::mods::mod::loading)
|
||||||
ircd::mods::mod::loading
|
ircd::mods::mod::loading
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
decltype(ircd::mods::mod::unloading)
|
||||||
|
ircd::mods::mod::unloading
|
||||||
|
{};
|
||||||
|
|
||||||
decltype(ircd::mods::mod::loaded)
|
decltype(ircd::mods::mod::loaded)
|
||||||
ircd::mods::mod::loaded
|
ircd::mods::mod::loaded
|
||||||
{};
|
{};
|
||||||
|
@ -818,17 +846,7 @@ bool ircd::mapi::static_destruction;
|
||||||
ircd::mods::mod::~mod()
|
ircd::mods::mod::~mod()
|
||||||
noexcept try
|
noexcept try
|
||||||
{
|
{
|
||||||
log::debug
|
|
||||||
{
|
|
||||||
log, "Attempting unload module '%s' @ `%s'",
|
|
||||||
name(),
|
|
||||||
location()
|
|
||||||
};
|
|
||||||
|
|
||||||
unload();
|
unload();
|
||||||
|
|
||||||
const size_t erased(loaded.erase(name()));
|
|
||||||
assert(erased == 1);
|
|
||||||
}
|
}
|
||||||
catch(const std::exception &e)
|
catch(const std::exception &e)
|
||||||
{
|
{
|
||||||
|
@ -849,6 +867,20 @@ ircd::mods::mod::unload()
|
||||||
if(!handle.is_loaded())
|
if(!handle.is_loaded())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if(mods::unloading(name()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Mark this module in the unloading state.
|
||||||
|
unloading.emplace_front(this);
|
||||||
|
|
||||||
|
log::debug
|
||||||
|
{
|
||||||
|
log, "Attempting unload module '%s' @ `%s'",
|
||||||
|
name(),
|
||||||
|
location()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call the user's unloading function here.
|
||||||
if(header->fini)
|
if(header->fini)
|
||||||
header->fini();
|
header->fini();
|
||||||
|
|
||||||
|
@ -860,6 +892,8 @@ ircd::mods::mod::unload()
|
||||||
std::for_each(rbegin(this->children), rend(this->children), []
|
std::for_each(rbegin(this->children), rend(this->children), []
|
||||||
(mod *const &ptr)
|
(mod *const &ptr)
|
||||||
{
|
{
|
||||||
|
// Only trigger an unload if there is one reference remaining to the module,
|
||||||
|
// in addition to the reference created by invoking shared_from() right here.
|
||||||
if(shared_from(*ptr).use_count() <= 2)
|
if(shared_from(*ptr).use_count() <= 2)
|
||||||
ptr->unload();
|
ptr->unload();
|
||||||
});
|
});
|
||||||
|
@ -874,7 +908,8 @@ ircd::mods::mod::unload()
|
||||||
mapi::static_destruction = false;
|
mapi::static_destruction = false;
|
||||||
handle.unload();
|
handle.unload();
|
||||||
assert(!handle.is_loaded());
|
assert(!handle.is_loaded());
|
||||||
|
loaded.erase(name());
|
||||||
|
unloading.remove(this);
|
||||||
if(!mapi::static_destruction)
|
if(!mapi::static_destruction)
|
||||||
{
|
{
|
||||||
log.critical("Module \"%s\" is stuck and failing to unload.", name());
|
log.critical("Module \"%s\" is stuck and failing to unload.", name());
|
||||||
|
|
|
@ -41,6 +41,7 @@ struct ircd::mods::mod
|
||||||
:std::enable_shared_from_this<mod>
|
:std::enable_shared_from_this<mod>
|
||||||
{
|
{
|
||||||
static std::forward_list<mod *> loading; // State of current dlopen() recursion.
|
static std::forward_list<mod *> loading; // State of current dlopen() recursion.
|
||||||
|
static std::forward_list<mod *> unloading; // dlclose() is not recursive but we have this
|
||||||
static std::map<string_view, mod *, std::less<>> loaded;
|
static std::map<string_view, mod *, std::less<>> loaded;
|
||||||
|
|
||||||
filesystem::path path;
|
filesystem::path path;
|
||||||
|
|
Loading…
Reference in a new issue