From 3402a3cd5d473d26c115145e19f4113db51e8435 Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 26 Aug 2012 13:24:37 +0400 Subject: [PATCH] Fix a deadlock problem between suspend in (un)load, and onupdate. --- library/PluginManager.cpp | 24 +++++++++++++++++------- library/include/PluginManager.h | 4 +++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/library/PluginManager.cpp b/library/PluginManager.cpp index d8b9ff27d..ceb644e60 100644 --- a/library/PluginManager.cpp +++ b/library/PluginManager.cpp @@ -186,14 +186,17 @@ Plugin::~Plugin() bool Plugin::load(color_ostream &con) { - RefAutolock lock(access); - if(state == PS_BROKEN) - { - return false; - } - else if(state == PS_LOADED) { - return true; + RefAutolock lock(access); + if(state == PS_LOADED) + { + return true; + } + else if(state != PS_UNLOADED) + { + return false; + } + state = PS_LOADING; } // enter suspend CoreSuspender suspend; @@ -202,6 +205,7 @@ bool Plugin::load(color_ostream &con) if(!plug) { con.printerr("Can't load plugin %s\n", filename.c_str()); + RefAutolock lock(access); state = PS_BROKEN; return false; } @@ -211,6 +215,7 @@ bool Plugin::load(color_ostream &con) { con.printerr("Plugin %s has no name or version.\n", filename.c_str()); ClosePlugin(plug); + RefAutolock lock(access); state = PS_BROKEN; return false; } @@ -219,9 +224,11 @@ bool Plugin::load(color_ostream &con) con.printerr("Plugin %s was not built for this version of DFHack.\n" "Plugin: %s, DFHack: %s\n", *plug_name, *plug_version, DFHACK_VERSION); ClosePlugin(plug); + RefAutolock lock(access); state = PS_BROKEN; return false; } + RefAutolock lock(access); plugin_init = (command_result (*)(color_ostream &, std::vector &)) LookupPlugin(plug, "plugin_init"); if(!plugin_init) { @@ -273,8 +280,11 @@ bool Plugin::unload(color_ostream &con) } // wait for all calls to finish access->wait(); + state = PS_UNLOADING; + access->unlock(); // enter suspend CoreSuspender suspend; + access->lock(); // notify plugin about shutdown, if it has a shutdown function command_result cr = CR_OK; if(plugin_shutdown) diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h index 25b05ad40..38f0e2e50 100644 --- a/library/include/PluginManager.h +++ b/library/include/PluginManager.h @@ -128,7 +128,9 @@ namespace DFHack { PS_UNLOADED, PS_LOADED, - PS_BROKEN + PS_BROKEN, + PS_LOADING, + PS_UNLOADING }; friend class PluginManager; friend class RPCService;