changeset 28395:a379987a74b0 stable

Make sure Objects and their proxy are initialized synchronously (bug #55225) * qt-graphics-toolkit.cc (qt_graphics_toolkit::qt_graphics_toolkit): use Qt::BlockingQueuedConnection to make sure the Object proxy "init" method has been called when we return. * ObjectProxy.h (sendFinalize, sendPrint): remove unused signals. * ObjectProxy.cc (ObjectProxy::ObjectProxy): Remove connections to slotPrint, and slotFinalize. (ObjectProxy::print): Use QMetaObject::invokeMethod with a Qt::BlockingQueuedConnection to execute slotPrint. Raise an error if either the GUI Object is not valid or invokeMethod failed. (ObjectProxy::finalize): Raise an error if either the GUI Object is not valid or invokeMethod failed. (ObjectProxy::get_pixels): Raise an error if the GUI Object is not valid. (ObjectProxy::setObject): Only call finalize with a valid GUI Object.
author Pantxo Diribarne <pantxo.diribarne@gmail.com>
date Tue, 26 May 2020 09:42:06 +0200
parents 0824d92a449d
children 4ea54a38c500 2a0e566a03e1
files libgui/graphics/ObjectProxy.cc libgui/graphics/ObjectProxy.h libgui/graphics/qt-graphics-toolkit.cc
diffstat 3 files changed, 28 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/ObjectProxy.cc	Mon Jun 01 23:37:34 2020 +0200
+++ b/libgui/graphics/ObjectProxy.cc	Tue May 26 09:42:06 2020 +0200
@@ -55,14 +55,10 @@
           {
             disconnect (this, SIGNAL (sendUpdate (int)),
                         m_object, SLOT (slotUpdate (int)));
-            disconnect (this, SIGNAL (sendFinalize (void)),
-                        m_object, SLOT (slotFinalize (void)));
             disconnect (this, SIGNAL (sendRedraw (void)),
                         m_object, SLOT (slotRedraw (void)));
             disconnect (this, SIGNAL (sendShow (void)),
                         m_object, SLOT (slotShow (void)));
-            disconnect (this, SIGNAL (sendPrint (const QString&, const QString&)),
-                        m_object, SLOT (slotPrint (const QString&, const QString&)));
           }
 
         m_object = obj;
@@ -71,15 +67,10 @@
           {
             connect (this, SIGNAL (sendUpdate (int)),
                      m_object, SLOT (slotUpdate (int)));
-            connect (this, SIGNAL (sendFinalize (void)),
-                     m_object, SLOT (slotFinalize (void)));
             connect (this, SIGNAL (sendRedraw (void)),
                      m_object, SLOT (slotRedraw (void)));
             connect (this, SIGNAL (sendShow (void)),
                      m_object, SLOT (slotShow (void)));
-            connect (this, SIGNAL (sendPrint (const QString&, const QString&)),
-                     m_object, SLOT (slotPrint (const QString&, const QString&)),
-                     Qt::BlockingQueuedConnection);
           }
       }
   }
@@ -87,7 +78,10 @@
   void
   ObjectProxy::setObject (Object *obj)
   {
-    finalize ();
+    // Eventually destroy previous Object
+    if (m_object)
+      finalize ();
+
     init (obj);
   }
 
@@ -101,14 +95,15 @@
   ObjectProxy::finalize (void)
   {
     if (! m_object)
-      return;
+      error ("ObjectProxy::finalize: invalid GUI Object");
 
     Qt::ConnectionType t = Qt::BlockingQueuedConnection;
 
     if (QThread::currentThread () == QCoreApplication::instance ()->thread ())
       t = Qt::DirectConnection;
 
-    QMetaObject::invokeMethod (m_object, "slotFinalize", t);
+    if (! QMetaObject::invokeMethod (m_object, "slotFinalize", t))
+      error ("ObjectProxy::finalize: unable to delete GUI Object");
   }
 
   void
@@ -126,12 +121,26 @@
   void
   ObjectProxy::print (const QString& file_cmd, const QString& term)
   {
-    emit sendPrint (file_cmd, term);
+    if (! m_object)
+      error ("ObjectProxy::print: invalid GUI Object");
+
+    Qt::ConnectionType t = Qt::BlockingQueuedConnection;
+
+    if (QThread::currentThread () == QCoreApplication::instance ()->thread ())
+      t = Qt::DirectConnection;
+
+    if (! QMetaObject::invokeMethod (m_object, "slotPrint", t,
+                                     Q_ARG (QString, file_cmd),
+                                     Q_ARG (QString, term)))
+      error ("ObjectProxy::print: unable to print figure");
   }
 
   uint8NDArray
   ObjectProxy::get_pixels (void)
   {
+    if (! m_object)
+      error ("ObjectProxy::finalize: invalid GUI Object");
+
     uint8NDArray retval;
 
     // The ObjectProxy is generally ran from the interpreter thread
--- a/libgui/graphics/ObjectProxy.h	Mon Jun 01 23:37:34 2020 +0200
+++ b/libgui/graphics/ObjectProxy.h	Tue May 26 09:42:06 2020 +0200
@@ -56,10 +56,8 @@
 
   signals:
     void sendUpdate (int pId);
-    void sendFinalize (void);
     void sendRedraw (void);
     void sendShow (void);
-    void sendPrint (const QString& file_cmd, const QString& term);
 
   private:
     void init (Object *obj);
--- a/libgui/graphics/qt-graphics-toolkit.cc	Mon Jun 01 23:37:34 2020 +0200
+++ b/libgui/graphics/qt-graphics-toolkit.cc	Tue May 26 09:42:06 2020 +0200
@@ -107,9 +107,14 @@
     // cross from the interpreter thread (where requests to create
     // graphics object are initiated) to the GUI application thread
     // (where they are actually created and displayed).
+    // We need to make sure the GUI Object and its proxy are properly
+    // created before the initialize method returns, so we use a
+    // BlockingQueuedConnection. After the signal is emitted, the interpreter
+    // thread is locked until the slot has returned.
 
     connect (this, SIGNAL (create_object_signal (double)),
-             this, SLOT (create_object (double)));
+             this, SLOT (create_object (double)),
+             Qt::BlockingQueuedConnection);
   }
 
   bool