[gnome-builder] terminal: dont spawn terminal from realize



commit 5db405ac812bd4a793b186bff7234e0425e40d2c
Author: Christian Hergert <chergert redhat com>
Date:   Tue Feb 22 13:45:35 2022 -0800

    terminal: dont spawn terminal from realize
    
    It can cause us to get into difficult issues with re-entrancy if the
    widget is removed during realize by the IdeGrid.

 src/libide/terminal/ide-terminal-page.c | 44 ++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 11 deletions(-)
---
diff --git a/src/libide/terminal/ide-terminal-page.c b/src/libide/terminal/ide-terminal-page.c
index 044f73d3f..27d913c32 100644
--- a/src/libide/terminal/ide-terminal-page.c
+++ b/src/libide/terminal/ide-terminal-page.c
@@ -172,19 +172,15 @@ ide_terminal_page_spawn_cb (GObject      *object,
   IDE_EXIT;
 }
 
-static void
-ide_terminal_page_realize (GtkWidget *widget)
+static gboolean
+ide_terminal_page_do_spawn_in_idle (IdeTerminalPage *self)
 {
-  IdeTerminalPage *self = (IdeTerminalPage *)widget;
+  IDE_ENTRY;
 
   g_assert (IDE_IS_TERMINAL_PAGE (self));
 
-  GTK_WIDGET_CLASS (ide_terminal_page_parent_class)->realize (widget);
-
-  if (self->did_defered_setup_in_realize)
-    return;
-
-  self->did_defered_setup_in_realize = TRUE;
+  if (self->destroyed)
+    IDE_RETURN (G_SOURCE_REMOVE);
 
   self->last_respawn = g_get_monotonic_time ();
 
@@ -195,14 +191,14 @@ ide_terminal_page_realize (GtkWidget *widget)
       if (!(self->pty = vte_pty_new_sync (VTE_PTY_DEFAULT, NULL, &error)))
         {
           g_critical ("Failed to create PTY for terminal: %s", error->message);
-          return;
+          IDE_RETURN (G_SOURCE_REMOVE);
         }
     }
 
   vte_terminal_set_pty (VTE_TERMINAL (self->terminal_top), self->pty);
 
   if (!self->manage_spawn)
-    return;
+    IDE_RETURN (G_SOURCE_REMOVE);
 
   /* Spawn our terminal and wait for it to exit */
   ide_terminal_launcher_spawn_async (self->launcher,
@@ -210,6 +206,32 @@ ide_terminal_page_realize (GtkWidget *widget)
                                      NULL,
                                      ide_terminal_page_spawn_cb,
                                      g_object_ref (self));
+
+  IDE_RETURN (G_SOURCE_REMOVE);
+}
+
+static void
+ide_terminal_page_realize (GtkWidget *widget)
+{
+  IdeTerminalPage *self = (IdeTerminalPage *)widget;
+
+  g_assert (IDE_IS_TERMINAL_PAGE (self));
+
+  GTK_WIDGET_CLASS (ide_terminal_page_parent_class)->realize (widget);
+
+  if (self->did_defered_setup_in_realize)
+    return;
+
+  self->did_defered_setup_in_realize = TRUE;
+
+  /* We don't want to process this in realize as it could be holding things
+   * up from being mapped. Instead, wait until the GDK backend has finished
+   * reacting to realize/etc and then spawn from idle.
+   */
+  g_idle_add_full (G_PRIORITY_LOW,
+                   (GSourceFunc)ide_terminal_page_do_spawn_in_idle,
+                   g_object_ref (self),
+                   g_object_unref);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]