server/state: Fix more unload synchronization

master
Perttu Ahola 2014-10-29 23:46:21 +02:00
parent bde862d05c
commit 40bf6f6bf0
1 changed files with 57 additions and 51 deletions

View File

@ -729,61 +729,70 @@ struct CState: public State, public interface::Server
}
// Direct version; internal and unsafe
// Call with m_modules_mutex locked.
// Call with no mutexes locked.
void unload_module_u(const ss_ &module_name)
{
log_i(MODULE, "unload_module_u(): module_name=%s", cs(module_name));
// Get and lock module
auto it = m_modules.find(module_name);
if(it == m_modules.end()){
log_w(MODULE, "unload_module_u(): Module not found: %s",
cs(module_name));
return;
}
sp_<ModuleContainer> mc = it->second;
sp_<ModuleContainer> mc;
{
interface::MutexScope mc_ms(mc->mutex);
// Delete subscriptions
log_t(MODULE, "unload_module_u[%s]: Deleting subscriptions",
cs(module_name));
{
for(Event::Type type = 0; type < m_event_subs.size(); type++){
sv_<wp_<ModuleContainer>> &sublist = m_event_subs[type];
sv_<wp_<ModuleContainer>> new_sublist;
for(wp_<ModuleContainer> &mc1 : sublist){
if(sp_<ModuleContainer>(mc1.lock()).get() !=
mc.get())
new_sublist.push_back(mc1);
else
log_v(MODULE, "Removing %s subscription to event %zu",
cs(module_name), type);
}
sublist = new_sublist;
}
interface::MutexScope ms(m_modules_mutex);
// Get and lock module
auto it = m_modules.find(module_name);
if(it == m_modules.end()){
log_w(MODULE, "unload_module_u(): Module not found: %s",
cs(module_name));
return;
}
mc = it->second;
{
interface::MutexScope mc_ms(mc->mutex);
// Delete subscriptions
log_t(MODULE, "unload_module_u[%s]: Deleting subscriptions",
cs(module_name));
{
for(Event::Type type = 0; type < m_event_subs.size(); type++){
sv_<wp_<ModuleContainer>> &sublist = m_event_subs[type];
sv_<wp_<ModuleContainer>> new_sublist;
for(wp_<ModuleContainer> &mc1 : sublist){
if(sp_<ModuleContainer>(mc1.lock()).get() !=
mc.get())
new_sublist.push_back(mc1);
else
log_v(MODULE, "Removing %s subscription to event %zu",
cs(module_name), type);
}
sublist = new_sublist;
}
}
// Remove server-wide reference to module container
m_modules.erase(module_name);
}
// Remove server-wide reference to module container
m_modules.erase(module_name);
}
// Destruct module
log_t(MODULE, "unload_module_u[%s]: Deleting module", cs(module_name));
mc->thread_request_stop();
mc->thread_join();
// So, hopefully this is the last reference because we're going to
// unload the shared executable...
if(!mc.unique())
log_w(MODULE, "unload_module_u[%s]: This is not the last container"
" reference; unloading shared executable is probably unsafe",
cs(module_name));
// Drop reference to container
log_t(MODULE, "unload_module_u[%s]: Dropping container", cs(module_name));
mc.reset();
// Unload shared executable
log_t(MODULE, "unload_module_u[%s]: Unloading shared executable",
cs(module_name));
m_compiler->unload(module_name);
emit_event(Event("core:module_unloaded",
new interface::ModuleUnloadedEvent(module_name)));
{
interface::MutexScope ms(m_modules_mutex);
// So, hopefully this is the last reference because we're going to
// unload the shared executable...
if(!mc.unique())
log_w(MODULE, "unload_module_u[%s]: This is not the last container"
" reference; unloading shared executable is probably unsafe",
cs(module_name));
// Drop reference to container
log_t(MODULE, "unload_module_u[%s]: Dropping container", cs(module_name));
mc.reset();
// Unload shared executable
log_t(MODULE, "unload_module_u[%s]: Unloading shared executable",
cs(module_name));
m_compiler->unload(module_name);
emit_event(Event("core:module_unloaded",
new interface::ModuleUnloadedEvent(module_name)));
}
}
ss_ get_modules_path()
@ -1081,13 +1090,10 @@ struct CState: public State, public interface::Server
module->event(Event::t("core:unload"), nullptr);
});
}
// Unload modules using unload_module_u()
{
interface::MutexScope ms(m_modules_mutex);
for(const ss_ &module_name : unloads_requested){
log_i(MODULE, "Unloading %s", cs(module_name));
unload_module_u(module_name);
}
// Unload modules
for(const ss_ &module_name : unloads_requested){
log_i(MODULE, "Unloading %s", cs(module_name));
unload_module_u(module_name);
}
// Load modules
for(const interface::ModuleInfo &info : loads_requested){