[Xfce4-commits] <xfce4-panel:devel> Handle the wrapper exit status.

Nick Schermer noreply at xfce.org
Wed Nov 18 13:04:01 CET 2009


Updating branch refs/heads/devel
         to 3cdd05b2b4e765c62a5f53df196410965fd5cd0a (commit)
       from 1a626a400017dc5f3f7f5c79ecf73b333f5b883b (commit)

commit 3cdd05b2b4e765c62a5f53df196410965fd5cd0a
Author: Nick Schermer <nick at xfce.org>
Date:   Wed Nov 18 13:03:14 2009 +0100

    Handle the wrapper exit status.

 panel/panel-plugin-external.c |  150 ++++++++++++++++++++++++++++++-----------
 1 files changed, 111 insertions(+), 39 deletions(-)

diff --git a/panel/panel-plugin-external.c b/panel/panel-plugin-external.c
index 601ca5e..49671f3 100644
--- a/panel/panel-plugin-external.c
+++ b/panel/panel-plugin-external.c
@@ -20,6 +20,13 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
 #include <exo/exo.h>
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
@@ -47,34 +54,38 @@
 
 
 
-static void         panel_plugin_external_provider_init       (XfcePanelPluginProviderIface    *iface);
-static void         panel_plugin_external_finalize            (GObject                         *object);
-static void         panel_plugin_external_realize             (GtkWidget                       *widget);
-static void         panel_plugin_external_unrealize           (GtkWidget                       *widget);
-static gboolean     panel_plugin_external_plug_removed        (GtkSocket                       *socket);
-static void         panel_plugin_external_plug_added          (GtkSocket                       *socket);
-static void         panel_plugin_external_provider_signal     (XfcePanelPluginProvider         *provider,
-                                                               XfcePanelPluginProviderSignal    signal);
-static const gchar *panel_plugin_external_get_name            (XfcePanelPluginProvider         *provider);
-static gint         panel_plugin_external_get_unique_id       (XfcePanelPluginProvider         *provider);
-static void         panel_plugin_external_set_size            (XfcePanelPluginProvider         *provider,
-                                                               gint                             size);
-static void         panel_plugin_external_set_orientation     (XfcePanelPluginProvider         *provider,
-                                                               GtkOrientation                   orientation);
-static void         panel_plugin_external_set_screen_position (XfcePanelPluginProvider         *provider,
-                                                               XfceScreenPosition               screen_position);
-static void         panel_plugin_external_save                (XfcePanelPluginProvider         *provider);
-static gboolean     panel_plugin_external_get_show_configure  (XfcePanelPluginProvider         *provider);
-static void         panel_plugin_external_show_configure      (XfcePanelPluginProvider         *provider);
-static gboolean     panel_plugin_external_get_show_about      (XfcePanelPluginProvider         *provider);
-static void         panel_plugin_external_show_about          (XfcePanelPluginProvider         *provider);
-static void         panel_plugin_external_remove              (XfcePanelPluginProvider         *provider);
-static void         panel_plugin_external_set_sensitive       (PanelPluginExternal             *external);
-static void         panel_plugin_external_set_property        (PanelPluginExternal             *external,
-                                                               DBusPropertyChanged              property,
-                                                               const GValue                    *value);
-static void         panel_plugin_external_set_property_noop   (PanelPluginExternal             *external,
-                                                               DBusPropertyChanged              property);
+static void         panel_plugin_external_provider_init         (XfcePanelPluginProviderIface    *iface);
+static void         panel_plugin_external_finalize              (GObject                         *object);
+static void         panel_plugin_external_realize               (GtkWidget                       *widget);
+static void         panel_plugin_external_unrealize             (GtkWidget                       *widget);
+static gboolean     panel_plugin_external_plug_removed          (GtkSocket                       *socket);
+static void         panel_plugin_external_plug_added            (GtkSocket                       *socket);
+static void         panel_plugin_external_provider_signal       (XfcePanelPluginProvider         *provider,
+                                                                 XfcePanelPluginProviderSignal    signal);
+static const gchar *panel_plugin_external_get_name              (XfcePanelPluginProvider         *provider);
+static gint         panel_plugin_external_get_unique_id         (XfcePanelPluginProvider         *provider);
+static void         panel_plugin_external_set_size              (XfcePanelPluginProvider         *provider,
+                                                                 gint                             size);
+static void         panel_plugin_external_set_orientation       (XfcePanelPluginProvider         *provider,
+                                                                 GtkOrientation                   orientation);
+static void         panel_plugin_external_set_screen_position   (XfcePanelPluginProvider         *provider,
+                                                                 XfceScreenPosition               screen_position);
+static void         panel_plugin_external_save                  (XfcePanelPluginProvider         *provider);
+static gboolean     panel_plugin_external_get_show_configure    (XfcePanelPluginProvider         *provider);
+static void         panel_plugin_external_show_configure        (XfcePanelPluginProvider         *provider);
+static gboolean     panel_plugin_external_get_show_about        (XfcePanelPluginProvider         *provider);
+static void         panel_plugin_external_show_about            (XfcePanelPluginProvider         *provider);
+static void         panel_plugin_external_remove                (XfcePanelPluginProvider         *provider);
+static void         panel_plugin_external_set_sensitive         (PanelPluginExternal             *external);
+static void         panel_plugin_external_set_property          (PanelPluginExternal             *external,
+                                                                 DBusPropertyChanged              property,
+                                                                 const GValue                    *value);
+static void         panel_plugin_external_set_property_noop     (PanelPluginExternal             *external,
+                                                                 DBusPropertyChanged              property);
+static void         panel_plugin_external_child_watch           (GPid                             pid,
+                                                                 gint                             status,
+                                                                 gpointer                         user_data);
+static void         panel_plugin_external_child_watch_destroyed (gpointer                         user_data);
 
 
 struct _PanelPluginExternalClass
@@ -101,12 +112,16 @@ struct _PanelPluginExternal
   /* dbus message queue */
   GSList           *dbus_queue;
 
-  /* counter to count the number of restart */
+  /* counter to count the number of restarts */
   guint             n_restarts;
 
   /* some info we store here */
   guint             show_configure : 1;
   guint             show_about : 1;
+
+  /* child watch data */
+  GPid              pid;
+  guint             watch_id;
 };
 
 typedef struct
@@ -189,6 +204,13 @@ panel_plugin_external_finalize (GObject *object)
   GSList              *li;
   QueuedData          *data;
 
+  if (external->watch_id != 0)
+    {
+      /* remove the child watch and don't leave zomies */
+      g_source_remove (external->watch_id);
+      g_child_watch_add (external->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
+    }
+
   /* cleanup */
   g_strfreev (external->arguments);
 
@@ -219,6 +241,7 @@ panel_plugin_external_realize (GtkWidget *widget)
   gchar                *socket_id, *unique_id;
   gint                  i, argc = 14;
   GdkScreen            *screen;
+  GPid                  pid;
 
   /* realize the socket first */
   (*GTK_WIDGET_CLASS (panel_plugin_external_parent_class)->realize) (widget);
@@ -258,21 +281,27 @@ panel_plugin_external_realize (GtkWidget *widget)
   screen = gtk_widget_get_screen (widget);
 
   /* spawn the proccess */
-  succeed = gdk_spawn_on_screen (screen, NULL, argv, NULL, 0, NULL, NULL, NULL, &error);
-
-  /* cleanup */
-  g_free (socket_id);
-  g_free (unique_id);
+  succeed = gdk_spawn_on_screen (screen, NULL, argv, NULL,
+                                 G_SPAWN_DO_NOT_REAP_CHILD, NULL,
+                                 NULL, &pid, &error);
 
-  /* handle problem */
-  if (G_UNLIKELY (succeed == FALSE))
+  if (G_LIKELY (succeed))
+    {
+      /* watch the child */
+      external->pid = pid;
+      external->watch_id = g_child_watch_add_full (G_PRIORITY_LOW, pid,
+                                                   panel_plugin_external_child_watch, external,
+                                                   panel_plugin_external_child_watch_destroyed);
+    }
+  else
     {
-      /* show warnings */
       g_critical ("Failed to spawn the xfce4-panel-wrapper: %s", error->message);
-
-      /* cleanup */
       g_error_free (error);
     }
+
+  /* cleanup */
+  g_free (socket_id);
+  g_free (unique_id);
 }
 
 
@@ -319,6 +348,13 @@ panel_plugin_external_plug_removed (GtkSocket *socket)
   gtk_widget_unrealize (GTK_WIDGET (socket));
   gtk_widget_hide (GTK_WIDGET (socket));
 
+  if (external->watch_id != 0)
+    {
+      /* remove the child watch and don't leave zomies */
+      g_source_remove (external->watch_id);
+      g_child_watch_add (external->pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
+    }
+
   /* increase the restart counter */
   external->n_restarts++;
 
@@ -362,6 +398,7 @@ panel_plugin_external_plug_removed (GtkSocket *socket)
     {
       /* get the plugin panel */
       window = PANEL_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket)));
+      panel_return_val_if_fail (PANEL_IS_WINDOW (window), FALSE);
 
       /* send panel information to the plugin */
       panel_window_set_povider_info (window, GTK_WIDGET (external));
@@ -700,6 +737,41 @@ panel_plugin_external_set_sensitive (PanelPluginExternal *external)
 
 
 
+static void
+panel_plugin_external_child_watch (GPid     pid,
+                                   gint     status,
+                                   gpointer user_data)
+{
+  PanelPluginExternal *external = PANEL_PLUGIN_EXTERNAL (user_data);
+
+  panel_return_if_fail (PANEL_IS_PLUGIN_EXTERNAL (external));
+  panel_return_if_fail (external->pid == pid);
+
+  switch (WEXITSTATUS (status))
+    {
+      case WRAPPER_EXIT_FAILURE:
+      case WRAPPER_EXIT_NO_PROVIDER:
+      case WRAPPER_EXIT_PREINIT:
+        /* wait until everything is settled, then destroy the
+         * external plugin so it is removed from the configuration */
+        exo_gtk_object_destroy_later (GTK_OBJECT (external));
+        break;
+    }
+
+  /* close the pid */
+  g_spawn_close_pid (pid);
+}
+
+
+
+static void
+panel_plugin_external_child_watch_destroyed (gpointer user_data)
+{
+  PANEL_PLUGIN_EXTERNAL (user_data)->watch_id = 0;
+}
+
+
+
 GtkWidget *
 panel_plugin_external_new (PanelModule  *module,
                            gint          unique_id,



More information about the Xfce4-commits mailing list