changeset 1768:70f544f9c38f

fix possible deadlock in custom database plugins
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 09 Nov 2015 17:39:42 +0100
parents b268756c2cb9
children cb466194f22c
files Plugins/Engine/OrthancPlugins.cpp
diffstat 1 files changed, 27 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/Plugins/Engine/OrthancPlugins.cpp	Mon Nov 09 09:34:18 2015 +0100
+++ b/Plugins/Engine/OrthancPlugins.cpp	Mon Nov 09 17:39:42 2015 +0100
@@ -1287,7 +1287,32 @@
   {
     VLOG(1) << "Calling service " << service << " from plugin " << plugin.GetPath();
 
-    boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_);
+    if (service == _OrthancPluginService_DatabaseAnswer)
+    {
+      // This case solves a deadlock at (*) reported by James Webster
+      // on 2015-10-27 that was present in versions of Orthanc <=
+      // 0.9.4 and related to database plugins implementing a custom
+      // index. The problem was that locking the database is already
+      // ensured by the "ServerIndex" class if the invoked service is
+      // "DatabaseAnswer".
+
+      const _OrthancPluginDatabaseAnswer& p =
+        *reinterpret_cast<const _OrthancPluginDatabaseAnswer*>(parameters);
+
+      if (pimpl_->database_.get() != NULL)
+      {
+        pimpl_->database_->AnswerReceived(p);
+        return true;
+      }
+      else
+      {
+        LOG(ERROR) << "Cannot invoke this service without a custom database back-end";
+        throw OrthancException(ErrorCode_BadRequest);
+      }
+    }
+
+
+    std::auto_ptr<boost::recursive_mutex::scoped_lock> lock;   // (*)
 
     switch (service)
     {
@@ -1559,21 +1584,7 @@
       }
 
       case _OrthancPluginService_DatabaseAnswer:
-      {
-        const _OrthancPluginDatabaseAnswer& p =
-          *reinterpret_cast<const _OrthancPluginDatabaseAnswer*>(parameters);
-
-        if (pimpl_->database_.get() != NULL)
-        {
-          pimpl_->database_->AnswerReceived(p);
-          return true;
-        }
-        else
-        {
-          LOG(ERROR) << "Cannot invoke this service without a custom database back-end";
-          throw OrthancException(ErrorCode_BadRequest);
-        }
-      }
+        throw OrthancException(ErrorCode_InternalError);   // Implemented before locking (*)
 
       case _OrthancPluginService_GetExpectedDatabaseVersion:
       {