changeset 25044:b6aea95a7bf9 stable

store graphics object in Qt backend to avoid crash (bug #53487, #53500) * Figure.cc (Figure::update): Return early if window doesn't exist. * Object.h, Object.cc (Object::m_go): New data member. (Object::object): Return m_go instead of using gh_manager to find it.
author John W. Eaton <jwe@octave.org>
date Wed, 28 Mar 2018 17:36:40 -0400
parents ba5af45bbfc4
children 135cc24efe4c a4c687fec320
files libgui/graphics/Figure.cc libgui/graphics/Object.cc libgui/graphics/Object.h
diffstat 3 files changed, 22 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/Figure.cc	Wed Mar 28 21:46:11 2018 +0200
+++ b/libgui/graphics/Figure.cc	Wed Mar 28 17:36:40 2018 -0400
@@ -438,6 +438,10 @@
 
     QMainWindow *win = qWidget<QMainWindow> ();
 
+    // If the window doesn't exist, there's nothing we can do.
+    if (! win)
+      return;
+
     m_blockUpdates = true;
 
     switch (pId)
--- a/libgui/graphics/Object.cc	Wed Mar 28 21:46:11 2018 +0200
+++ b/libgui/graphics/Object.cc	Wed Mar 28 17:36:40 2018 -0400
@@ -35,7 +35,7 @@
 {
 
   Object::Object (const graphics_object& go, QObject *obj)
-    : QObject (), m_handle (go.get_handle ()), m_qobject (nullptr)
+    : QObject (), m_go (go), m_handle (go.get_handle ()), m_qobject (nullptr)
   {
     gh_manager::auto_lock lock (false);
 
@@ -78,7 +78,7 @@
                  "accessing graphics object (h=%g) without a valid lock!!!",
                  m_handle.value ());
 
-    return gh_manager::get_object (m_handle);
+    return m_go;
   }
 
   void
--- a/libgui/graphics/Object.h	Wed Mar 28 21:46:11 2018 +0200
+++ b/libgui/graphics/Object.h	Wed Mar 28 17:36:40 2018 -0400
@@ -97,7 +97,23 @@
     virtual void beingDeleted (void);
 
   protected:
+
+    // Store the graphics object directly so that it will exist when
+    // we need it.  Previously, it was possible for the graphics
+    // backend to get a handle to a figure, then have the interpreter
+    // thread delete the corresponding object before the backend (GUI)
+    // thread had a chance to display it.  It should be OK to store
+    // this object and use it in both threads (graphics_object uses a
+    // std::shared_ptr) provided that we protect access with mutex locks.
+    graphics_object m_go;
+
+    // Handle to the graphics object.  This may be redundant now.
+    // Also, the whole ObjectProxy thing may not need to store a
+    // pointer now?  Maybe we can just have a lookup table from figure
+    // handle to Object?  What does the FLTK toolkit do?  Why does
+    // this seem to be so complicated?
     graphics_handle m_handle;
+
     QObject *m_qobject;
   };