diff Framework/Oracle/WebAssemblyOracle.cpp @ 973:38409549db43 toa2019082903

Log with addresses + added fingerprint mechanism to avoid calling zombie objects where: - a message is sent with a receiver - the receiver dies - another receiver with the SAME address is created - the message reply is executed --> execution on the wrong object! (since their "identity" is their address. The fix is to identify them with an UUID stored at creation time)
author Benjamin Golinvaux <bgo@osimis.io>
date Thu, 29 Aug 2019 18:07:55 +0200
parents bc7b249dfbd0
children e75fd08d6c75
line wrap: on
line diff
--- a/Framework/Oracle/WebAssemblyOracle.cpp	Thu Aug 29 13:12:03 2019 +0200
+++ b/Framework/Oracle/WebAssemblyOracle.cpp	Thu Aug 29 18:07:55 2019 +0200
@@ -99,6 +99,7 @@
   private:
     Emitter                        emitter_;
     const IObserver&               receiver_;
+    std::string                    receiverFingerprint_;
     std::auto_ptr<IOracleCommand>  command_;
     std::string                    expectedContentType_;
 
@@ -109,6 +110,7 @@
                  const std::string& expectedContentType) :
       emitter_(oracle),
       receiver_(receiver),
+      receiverFingerprint_(receiver.GetFingerprint()),
       command_(command),
       expectedContentType_(expectedContentType)
     {
@@ -118,6 +120,16 @@
       }
     }
 
+    bool IsFingerprintOK() const
+    {
+      bool ok = receiverFingerprint_ == receiver_.GetFingerprint();
+      if (!ok)
+      {
+        LOG(TRACE) << "IsFingerprintOK returned false. receiverFingerprint_ = " << receiverFingerprint_ << " | receiver_(" << std::hex << (&receiver_) << std::dec << ").GetFingerprint() = " << receiver_.GetFingerprint();
+      }
+      return ok;
+    }
+
     const std::string& GetExpectedContentType() const
     {
       return expectedContentType_;
@@ -195,6 +207,7 @@
        **/
       
       std::auto_ptr<FetchContext> context(reinterpret_cast<FetchContext*>(fetch->userData));
+
       if (fetch->userData == NULL)
       {
         LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback fetch->userData is NULL!!!!!!!";
@@ -234,49 +247,57 @@
 
       /**
        * Secondly, use the retrieved data.
+       * We only use the receiver if its fingerprint matches the one stored
+       * at command creation. 
        **/
-
-      try
+      if (!context->IsFingerprintOK())
       {
-        if (context.get() == NULL)
+        LOG(WARNING) << "FetchContext::SuccessCallback -- the initial request initiator has been destroyed. Response will be discarded.";
+      }
+      else
+      {
+        try
         {
-          throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
-        }
-        else
-        {
-          switch (context->GetCommand().GetType())
+          if (context.get() == NULL)
           {
+            throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+          }
+          else
+          {
+            switch (context->GetCommand().GetType())
+            {
             case IOracleCommand::Type_OrthancRestApi:
             {
               OrthancRestApiCommand::SuccessMessage message
-                (context->GetTypedCommand<OrthancRestApiCommand>(), headers, answer);
+              (context->GetTypedCommand<OrthancRestApiCommand>(), headers, answer);
               context->EmitMessage(message);
               break;
             }
-            
+
             case IOracleCommand::Type_GetOrthancImage:
             {
               context->GetTypedCommand<GetOrthancImageCommand>().ProcessHttpAnswer
-                (context->GetEmitter(), context->GetReceiver(), answer, headers);
+              (context->GetEmitter(), context->GetReceiver(), answer, headers);
               break;
             }
-          
+
             case IOracleCommand::Type_GetOrthancWebViewerJpeg:
             {
               context->GetTypedCommand<GetOrthancWebViewerJpegCommand>().ProcessHttpAnswer
-                (context->GetEmitter(), context->GetReceiver(), answer);
+              (context->GetEmitter(), context->GetReceiver(), answer);
               break;
             }
-          
+
             default:
               LOG(ERROR) << "Command type not implemented by the WebAssembly Oracle: "
-                         << context->GetCommand().GetType();
+                << context->GetCommand().GetType();
+            }
           }
         }
-      }
-      catch (Orthanc::OrthancException& e)
-      {
-        LOG(ERROR) << "Error while processing a fetch answer in the oracle: " << e.What();
+        catch (Orthanc::OrthancException& e)
+        {
+          LOG(ERROR) << "Error while processing a fetch answer in the oracle: " << e.What();
+        }
       }
     }