[gnome-disk-utility] Track ssh connection and emit GduPool::disconnected as appropriate



commit 00b907518c1b4f8c1731c2a6a3f08b4d65520b84
Author: David Zeuthen <davidz redhat com>
Date:   Fri Dec 11 19:08:43 2009 -0500

    Track ssh connection and emit GduPool::disconnected as appropriate
    
    Also act on this signal in Palimpsest. Still need to add a disconnect
    button for the user to press.
    
    Signed-off-by: David Zeuthen <davidz redhat com>

 src/gdu/gdu-pool.c         |  126 +++++++++++++++++++++++++++++++++++++++-----
 src/gdu/gdu-pool.h         |    2 +
 src/gdu/gdu-ssh-bridge.c   |   22 +++++---
 src/gdu/gdu-ssh-bridge.h   |    4 +-
 src/palimpsest/gdu-shell.c |   13 +++++
 5 files changed, 142 insertions(+), 25 deletions(-)
---
diff --git a/src/gdu/gdu-pool.c b/src/gdu/gdu-pool.c
index e3630de..1090ebe 100644
--- a/src/gdu/gdu-pool.c
+++ b/src/gdu/gdu-pool.c
@@ -55,6 +55,7 @@
  */
 
 enum {
+        DISCONNECTED,
         DEVICE_ADDED,
         DEVICE_REMOVED,
         DEVICE_CHANGED,
@@ -78,10 +79,16 @@ enum {
 static GObjectClass *parent_class = NULL;
 static guint signals[LAST_SIGNAL] = { 0 };
 
+static void _gdu_pool_disconnect (GduPool *pool);
+
 struct _GduPoolPrivate
 {
+        gboolean is_disconnected;
+
         gchar *ssh_user_name;
         gchar *ssh_address;
+        GPid ssh_pid;
+        guint ssh_child_watch_id;
 
         DBusGConnection *bus;
         DBusGProxy *proxy;
@@ -108,29 +115,28 @@ struct _GduPoolPrivate
 
 G_DEFINE_TYPE (GduPool, gdu_pool, G_TYPE_OBJECT);
 
+static void remove_all_objects_and_dbus_proxies (GduPool *pool);
+
 static void
 gdu_pool_finalize (GduPool *pool)
 {
-        if (pool->priv->bus != NULL)
-                dbus_g_connection_unref (pool->priv->bus);
-        if (pool->priv->proxy != NULL)
-                g_object_unref (pool->priv->proxy);
-
-        g_free (pool->priv->daemon_version);
+        g_print ("in gdu_pool_finalize()\n");
 
-        g_list_foreach (pool->priv->known_filesystems, (GFunc) g_object_unref, NULL);
-        g_list_free (pool->priv->known_filesystems);
+        remove_all_objects_and_dbus_proxies (pool);
 
         g_hash_table_unref (pool->priv->object_path_to_device);
-
         g_hash_table_unref (pool->priv->object_path_to_adapter);
-
         g_hash_table_unref (pool->priv->object_path_to_expander);
-
         g_hash_table_unref (pool->priv->object_path_to_port);
 
-        g_list_foreach (pool->priv->presentables, (GFunc) g_object_unref, NULL);
-        g_list_free (pool->priv->presentables);
+        if (pool->priv->ssh_child_watch_id > 0) {
+                g_source_remove (pool->priv->ssh_child_watch_id);
+                pool->priv->ssh_child_watch_id = 0;
+        }
+        if (pool->priv->ssh_pid > 0) {
+                kill (pool->priv->ssh_pid, SIGTERM);
+                pool->priv->ssh_pid = 0;
+        }
 
         if (G_OBJECT_CLASS (parent_class)->finalize)
                 (* G_OBJECT_CLASS (parent_class)->finalize) (G_OBJECT (pool));
@@ -148,6 +154,25 @@ gdu_pool_class_init (GduPoolClass *klass)
         g_type_class_add_private (klass, sizeof (GduPoolPrivate));
 
         /**
+         * GduPool::disconnected
+         * @pool: The #GduPool emitting the signal.
+         *
+         * Emitted when the underlying connection has been disconnected.
+         *
+         * If you hold a reference to @pool, now is a good time to give it up.
+         */
+        signals[DISCONNECTED] =
+                g_signal_new ("disconnected",
+                              G_TYPE_FROM_CLASS (klass),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GduPoolClass, disconnected),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+
+        /**
          * GduPool::device-added
          * @pool: The #GduPool emitting the signal.
          * @device: The #GduDevice that was added.
@@ -1711,6 +1736,31 @@ _gdu_pool_get_connection (GduPool *pool)
         return pool->priv->bus;
 }
 
+static void
+on_ssh_process_terminated (GPid     pid,
+                           gint     status,
+                           gpointer user_data)
+{
+        GduPool *pool = GDU_POOL (user_data);
+
+        g_print ("wohoo, ssh process has been terminated\n");
+
+        /* need to take a temp ref since receivers of the ::disconnected signal
+         * may unref the pool
+         */
+        g_object_ref (pool);
+
+        _gdu_pool_disconnect (pool);
+
+        g_spawn_close_pid (pid);
+
+        g_source_remove (pool->priv->ssh_child_watch_id);
+        pool->priv->ssh_child_watch_id = 0;
+        pool->priv->ssh_pid = 0;
+
+        g_object_unref (pool);
+}
+
 GduPool *
 gdu_pool_new_for_address (const gchar     *ssh_user_name,
                           const gchar     *ssh_address,
@@ -1734,12 +1784,21 @@ gdu_pool_new_for_address (const gchar     *ssh_user_name,
                         goto error;
                 }
         } else {
-                pool->priv->bus = _gdu_ssh_bridge_connect (pool, ssh_user_name, ssh_address, error);
+                pool->priv->bus = _gdu_ssh_bridge_connect (ssh_user_name,
+                                                           ssh_address,
+                                                           &(pool->priv->ssh_pid),
+                                                           error);
                 if (pool->priv->bus == NULL) {
                         goto error;
                 }
                 pool->priv->ssh_user_name = g_strdup (ssh_user_name);
                 pool->priv->ssh_address  = g_strdup (ssh_address);
+
+                /* Watch the ssh process */
+                g_print ("pid is %d\n", pool->priv->ssh_pid);
+                pool->priv->ssh_child_watch_id = g_child_watch_add (pool->priv->ssh_pid,
+                                                                    on_ssh_process_terminated,
+                                                                    pool);
         }
 
         dbus_g_object_register_marshaller (
@@ -2719,3 +2778,42 @@ gdu_pool_get_ssh_address (GduPool *pool)
         return pool->priv->ssh_address;
 }
 
+static void
+remove_all_objects_and_dbus_proxies (GduPool *pool)
+{
+        g_free (pool->priv->daemon_version);
+        pool->priv->daemon_version = NULL;
+
+        g_list_foreach (pool->priv->known_filesystems, (GFunc) g_object_unref, NULL);
+        g_list_free (pool->priv->known_filesystems);
+        pool->priv->known_filesystems = NULL;
+
+        g_hash_table_remove_all (pool->priv->object_path_to_device);
+        g_hash_table_remove_all (pool->priv->object_path_to_adapter);
+        g_hash_table_remove_all (pool->priv->object_path_to_expander);
+        g_hash_table_remove_all (pool->priv->object_path_to_port);
+
+        g_list_foreach (pool->priv->presentables, (GFunc) g_object_unref, NULL);
+        g_list_free (pool->priv->presentables);
+        pool->priv->presentables = NULL;
+
+        if (pool->priv->proxy != NULL) {
+                g_object_unref (pool->priv->proxy);
+                pool->priv->proxy = NULL;
+        }
+
+        if (pool->priv->bus != NULL) {
+                dbus_g_connection_unref (pool->priv->bus);
+                pool->priv->bus = NULL;
+        }
+}
+
+static void
+_gdu_pool_disconnect (GduPool *pool)
+{
+        g_return_if_fail (!pool->priv->is_disconnected);
+
+        remove_all_objects_and_dbus_proxies (pool);
+        pool->priv->is_disconnected = TRUE;
+        g_signal_emit (pool, signals[DISCONNECTED], 0);
+}
diff --git a/src/gdu/gdu-pool.h b/src/gdu/gdu-pool.h
index 0bb5d38..9605402 100644
--- a/src/gdu/gdu-pool.h
+++ b/src/gdu/gdu-pool.h
@@ -54,6 +54,8 @@ struct _GduPoolClass
         GObjectClass parent_class;
 
         /* signals */
+        void (*disconnected) (GduPool *pool);
+
         void (*device_added) (GduPool *pool, GduDevice *device);
         void (*device_removed) (GduPool *pool, GduDevice *device);
         void (*device_changed) (GduPool *pool, GduDevice *device);
diff --git a/src/gdu/gdu-ssh-bridge.c b/src/gdu/gdu-ssh-bridge.c
index b5780a5..09ee4a7 100644
--- a/src/gdu/gdu-ssh-bridge.c
+++ b/src/gdu/gdu-ssh-bridge.c
@@ -25,6 +25,11 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 #include <gio/gunixinputstream.h>
 #include <gio/gunixoutputstream.h>
@@ -183,12 +188,6 @@ on_new_connection (DBusServer     *server,
         ;
 }
 
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
 static void
 child_setup (gpointer user_data)
 {
@@ -222,9 +221,9 @@ fixup_newlines (gchar *s)
 
 
 DBusGConnection *
-_gdu_ssh_bridge_connect (GduPool          *pool,
-                         const gchar      *ssh_user_name,
+_gdu_ssh_bridge_connect (const gchar      *ssh_user_name,
                          const gchar      *ssh_address,
+                         GPid             *out_pid,
                          GError          **error)
 {
         BridgeData *data;
@@ -356,7 +355,7 @@ _gdu_ssh_bridge_connect (GduPool          *pool,
         if (!g_spawn_async_with_pipes (NULL,
                                        ssh_argv,
                                        NULL,
-                                       G_SPAWN_SEARCH_PATH,
+                                       G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
                                        child_setup,
                                        NULL,
                                        &ssh_pid,
@@ -599,6 +598,11 @@ _gdu_ssh_bridge_connect (GduPool          *pool,
                 if (ssh_pid > 0) {
                         kill (ssh_pid, SIGTERM);
                 }
+                if (out_pid != NULL)
+                        *out_pid = 0;
+        } else {
+                if (out_pid != NULL)
+                        *out_pid = ssh_pid;
         }
 
         if (data != NULL)
diff --git a/src/gdu/gdu-ssh-bridge.h b/src/gdu/gdu-ssh-bridge.h
index 73758ba..23e4b61 100644
--- a/src/gdu/gdu-ssh-bridge.h
+++ b/src/gdu/gdu-ssh-bridge.h
@@ -29,9 +29,9 @@
 #include <dbus/dbus-glib.h>
 #include "gdu-types.h"
 
-DBusGConnection * _gdu_ssh_bridge_connect (GduPool          *pool,
-                                           const gchar      *ssh_user_name,
+DBusGConnection * _gdu_ssh_bridge_connect (const gchar      *ssh_user_name,
                                            const gchar      *ssh_address,
+                                           GPid             *out_pid,
                                            GError          **error);
 
 #endif /* __GDU_SSH_BRIDGE_H */
diff --git a/src/palimpsest/gdu-shell.c b/src/palimpsest/gdu-shell.c
index 1a5ede3..3d92509 100644
--- a/src/palimpsest/gdu-shell.c
+++ b/src/palimpsest/gdu-shell.c
@@ -1116,6 +1116,18 @@ gdu_shell_raise_error (GduShell       *shell,
         g_free (error_text);
 }
 
+static void
+pool_disconnected (GduPool  *pool,
+                   gpointer user_data)
+{
+        GduShell *shell = GDU_SHELL (user_data);
+
+        g_warn_if_fail (g_ptr_array_remove (shell->priv->pools, pool));
+        g_object_unref (pool);
+
+        gdu_pool_tree_model_set_pools (shell->priv->model, shell->priv->pools);
+}
+
 static gboolean
 add_pool (GduShell     *shell,
           const gchar  *ssh_user_name,
@@ -1133,6 +1145,7 @@ add_pool (GduShell     *shell,
 
         g_signal_connect (pool, "presentable-added", (GCallback) presentable_added, shell);
         g_signal_connect (pool, "presentable-removed", (GCallback) presentable_removed, shell);
+        g_signal_connect (pool, "disconnected", (GCallback) pool_disconnected, shell);
 
         g_ptr_array_add (shell->priv->pools, pool);
 



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