diff Applications/Platforms/WebAssembly/WebAssemblyViewport.cpp @ 1621:575f512cdf48

Used a weak_ptr as a cookie to RequestAnimationFrame to prevent accessing a deleted viewport.
author Benjamin Golinvaux <bgo@osimis.io>
date Mon, 02 Nov 2020 20:45:04 +0100
parents 9a52bac0c2a7
children 74be0f498b08
line wrap: on
line diff
--- a/Applications/Platforms/WebAssembly/WebAssemblyViewport.cpp	Mon Nov 02 17:56:49 2020 +0100
+++ b/Applications/Platforms/WebAssembly/WebAssemblyViewport.cpp	Mon Nov 02 20:45:04 2020 +0100
@@ -120,19 +120,27 @@
     }
   };
 
-
   EM_BOOL WebAssemblyViewport::OnRequestAnimationFrame(double time, void *userData)
   {
     LOG(TRACE) << __func__;
-    WebAssemblyViewport* that = reinterpret_cast<WebAssemblyViewport*>(userData);
 
-    if (that->compositor_.get() != NULL &&
-        that->controller_ /* should always be true */)
+    WebAssemblyViewport* that = 
+      WebAssemblyViewport::DereferenceObjectCookie(userData);
+    
+    if (that != NULL)
     {
-      that->animationFrameCallbackIds_.clear();
-      that->Paint(*that->compositor_, *that->controller_);
+      if (that->compositor_.get() != NULL &&
+          that->controller_ /* should always be true */)
+      {
+        that->Paint(*that->compositor_, *that->controller_);
+      }
+    } 
+    else
+    {
+      LOG(INFO) << "WebAssemblyViewport::OnRequestAnimationFrame " 
+        << "-- the WebAssemblyViewport is deleted and Paint will " 
+        << "not be called";
     }
-      
     LOG(TRACE) << "Exiting: " << __func__;
     return true;
   }
@@ -212,10 +220,48 @@
     return true;
   }
 
+  void* WebAssemblyViewport::GetObjectCookie()
+  {
+    if(objectCookie_ != NULL)
+      return objectCookie_;
+    
+    boost::shared_ptr<WebAssemblyViewport>* sharedFromThisPtr = 
+      new boost::shared_ptr<WebAssemblyViewport>();
+    
+    *sharedFromThisPtr = shared_from_this();
+
+    objectCookie_ = reinterpret_cast<void*>(sharedFromThisPtr);
+    
+    return objectCookie_;
+  }
+
+  void WebAssemblyViewport::ReleaseObjectCookie(void* cookie)
+  {
+    WebAssemblyViewport* This = DereferenceObjectCookie(cookie);
+    
+    if (This != NULL)
+      This->objectCookie_ = NULL;
+
+    boost::weak_ptr<WebAssemblyViewport>* weakThisPtr = 
+      reinterpret_cast<boost::weak_ptr<WebAssemblyViewport>*>(cookie);
+    
+    delete weakThisPtr;
+  }
+
+  WebAssemblyViewport* WebAssemblyViewport::DereferenceObjectCookie(void* cookie)
+  {
+    boost::weak_ptr<WebAssemblyViewport>* weakThisPtr = 
+      reinterpret_cast<boost::weak_ptr<WebAssemblyViewport>*>(cookie);
+
+    boost::shared_ptr<WebAssemblyViewport> sharedThis = weakThisPtr->lock();
+
+    return sharedThis.get();
+  }
+
   void WebAssemblyViewport::Invalidate()
   {
     long id = emscripten_request_animation_frame(OnRequestAnimationFrame, 
-                                                 reinterpret_cast<void*>(this));
+                                                 GetObjectCookie());
     animationFrameCallbackIds_.push_back(id);
   }
 
@@ -259,7 +305,8 @@
     interactor_(new DefaultViewportInteractor),
     enableEmscriptenMouseEvents_(enableEmscriptenMouseEvents),
     canvasWidth_(0),
-    canvasHeight_(0)
+    canvasHeight_(0),
+    objectCookie_(NULL)
   {
   }