gvfs r1522 - in trunk: . client hal



Author: alexl
Date: Tue Mar  4 11:20:26 2008
New Revision: 1522
URL: http://svn.gnome.org/viewvc/gvfs?rev=1522&view=rev

Log:
2008-03-04  Alexander Larsson  <alexl redhat com>

        * client/gdaemonmount.c:
        * client/gdaemonvolumemonitor.c:
        * hal/ghaldrive.c:
        * hal/ghalmount.c:
        * hal/ghalvolume.c:
        * hal/ghalvolumemonitor.[ch]:
	Properly lock around volume monitors and
	volume monitor objects.
	Emit all events in idles to avoid reentrancy
	issues. Fixed deadlock in #519599.



Modified:
   trunk/ChangeLog
   trunk/client/gdaemonmount.c
   trunk/client/gdaemonvolumemonitor.c
   trunk/hal/ghaldrive.c
   trunk/hal/ghalmount.c
   trunk/hal/ghalvolume.c
   trunk/hal/ghalvolumemonitor.c
   trunk/hal/ghalvolumemonitor.h

Modified: trunk/client/gdaemonmount.c
==============================================================================
--- trunk/client/gdaemonmount.c	(original)
+++ trunk/client/gdaemonmount.c	Tue Mar  4 11:20:26 2008
@@ -34,6 +34,10 @@
 #include "gvfsdaemonprotocol.h"
 #include "gdbusutils.h"
 
+/* Protects all fields of GDaemonMount that can change
+   which at this point is just foreign_volume */
+G_LOCK_DEFINE_STATIC(daemon_mount);
+
 struct _GDaemonMount {
   GObject     parent;
 
@@ -146,9 +150,14 @@
 g_daemon_mount_get_drive (GMount *mount)
 {
   GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
+  GDrive *drive;
+
+  G_LOCK (daemon_mount);
+  drive = NULL;
   if (daemon_mount->foreign_volume != NULL)
-    return g_volume_get_drive (daemon_mount->foreign_volume);
-  return NULL;
+    drive = g_volume_get_drive (daemon_mount->foreign_volume);
+  G_UNLOCK (daemon_mount);
+  return drive;
 }
 
 static gboolean
@@ -161,23 +170,44 @@
 g_daemon_mount_can_eject (GMount *mount)
 {
   GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
+  gboolean res;
+  
+  G_LOCK (daemon_mount);
+  res = FALSE;
   if (daemon_mount->foreign_volume != NULL)
-    return g_volume_can_eject (daemon_mount->foreign_volume);
-  return FALSE;
+    res = g_volume_can_eject (daemon_mount->foreign_volume);
+  G_UNLOCK (daemon_mount);
+  
+  return res;
 }
 
 static void
 foreign_volume_removed (GVolume *volume, gpointer user_data)
 {
   GDaemonMount *daemon_mount = G_DAEMON_MOUNT (user_data);
+
+  G_LOCK (daemon_mount);
+
+  g_object_ref (daemon_mount);
+  
   if (daemon_mount->foreign_volume == volume)
     g_daemon_mount_set_foreign_volume (daemon_mount, NULL);
+
+  G_UNLOCK (daemon_mount);
+  
+  g_signal_emit_by_name (daemon_mount, "changed");
+  if (daemon_mount->volume_monitor != NULL)
+    g_signal_emit_by_name (daemon_mount->volume_monitor, "mount_changed", daemon_mount);
+  
+  g_object_unref (daemon_mount);
 }
 
 void
 g_daemon_mount_set_foreign_volume (GDaemonMount *mount, 
                                    GVolume *foreign_volume)
 {
+  G_LOCK (daemon_mount);
+  
   if (mount->foreign_volume != NULL)
     g_object_unref (mount->foreign_volume);
 
@@ -189,9 +219,7 @@
   else
     mount->foreign_volume = NULL;
 
-  g_signal_emit_by_name (mount, "changed");
-  if (mount->volume_monitor != NULL)
-    g_signal_emit_by_name (mount->volume_monitor, "mount_changed", mount);
+  G_UNLOCK (daemon_mount);
 }
 
 static void
@@ -278,18 +306,23 @@
   GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
   GDrive *drive;
 
+  G_LOCK (daemon_mount);
+
+  drive = NULL;
   if (daemon_mount->foreign_volume != NULL)
+    drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume));
+      
+  G_UNLOCK (daemon_mount);
+  
+  if (drive != NULL)
     {
-      drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume));
-      if (drive != NULL)
-        {
-          EjectWrapperOp *data;
-          data = g_new0 (EjectWrapperOp, 1);
-          data->object = G_OBJECT (mount);
-          data->callback = callback;
-          data->user_data = user_data;
-          g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
-        }
+      EjectWrapperOp *data;
+      data = g_new0 (EjectWrapperOp, 1);
+      data->object = G_OBJECT (mount);
+      data->callback = callback;
+      data->user_data = user_data;
+      g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
+      g_object_unref (drive);
     }
 }
 
@@ -300,14 +333,24 @@
 {
   GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
   GDrive *drive;
+  gboolean res;
+
+  res = TRUE;
 
+  G_LOCK (daemon_mount);
+  
   if (daemon_mount->foreign_volume != NULL)
+    drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume));
+
+  G_UNLOCK (daemon_mount);
+  
+  if (drive != NULL)
     {
-      drive = g_volume_get_drive (G_VOLUME (daemon_mount->foreign_volume));
-      if (drive != NULL)
-        return g_drive_eject_finish (drive, result, error);
+      res = g_drive_eject_finish (drive, result, error);
+      g_object_unref (drive);
     }
-  return TRUE;
+  
+  return res;
 }
 
 static void

Modified: trunk/client/gdaemonvolumemonitor.c
==============================================================================
--- trunk/client/gdaemonvolumemonitor.c	(original)
+++ trunk/client/gdaemonvolumemonitor.c	Tue Mar  4 11:20:26 2008
@@ -33,7 +33,7 @@
 #include "gdaemonvfs.h"
 #include "gmounttracker.h"
 
-G_LOCK_DEFINE_STATIC(_the_daemon_volume_monitor);
+G_LOCK_DEFINE_STATIC(daemon_vm);
 
 static GDaemonVolumeMonitor *_the_daemon_volume_monitor;
 
@@ -52,14 +52,14 @@
   GDaemonVolumeMonitor *monitor;
   GList *l;
 
-  G_LOCK (_the_daemon_volume_monitor);
+  G_LOCK (daemon_vm);
 
   monitor = G_DAEMON_VOLUME_MONITOR (volume_monitor);
 
   l = g_list_copy (monitor->mounts);
   g_list_foreach (l, (GFunc)g_object_ref, NULL);
 
-  G_UNLOCK (_the_daemon_volume_monitor);
+  G_UNLOCK (daemon_vm);
 
   return l;
 }
@@ -84,7 +84,6 @@
   return NULL;
 }
 
-
 static GMount *
 get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid)
 {
@@ -118,20 +117,18 @@
 {
   GDaemonMount *daemon_mount;
 
-  if (_the_daemon_volume_monitor == NULL)
-    {
-      return NULL;
-    }
-
-  G_LOCK (_the_daemon_volume_monitor);
+  G_LOCK (daemon_vm);
 
-  daemon_mount = find_mount_by_mount_info (_the_daemon_volume_monitor, mount_info);
-  if (daemon_mount != NULL)
+  daemon_mount = NULL;
+  if (_the_daemon_volume_monitor != NULL)
     {
-      g_object_ref (daemon_mount);
+      daemon_mount = find_mount_by_mount_info (_the_daemon_volume_monitor, mount_info);
+      
+      if (daemon_mount != NULL)
+        g_object_ref (daemon_mount);
     }
 
-  G_UNLOCK (_the_daemon_volume_monitor);
+  G_UNLOCK (daemon_vm);
 
   return daemon_mount;
 }
@@ -142,14 +139,14 @@
   GDaemonMount *mount;
   GVolume *volume;
 
-  G_LOCK (_the_daemon_volume_monitor);
+  G_LOCK (daemon_vm);
 
   mount = find_mount_by_mount_info (daemon_monitor, mount_info);
   if (mount)
     {
       g_warning (G_STRLOC ": Mount was added twice!");
       
-      G_UNLOCK (_the_daemon_volume_monitor);
+      G_UNLOCK (daemon_vm);
       return;
     }
 
@@ -165,7 +162,7 @@
       g_object_ref (mount);
     }
   
-  G_UNLOCK (_the_daemon_volume_monitor);
+  G_UNLOCK (daemon_vm);
 
   if (mount)
     {
@@ -180,7 +177,7 @@
 {
   GDaemonMount *mount;
 
-  G_LOCK (_the_daemon_volume_monitor);
+  G_LOCK (daemon_vm);
 
   mount = find_mount_by_mount_info (daemon_monitor, mount_info);
   if (!mount)
@@ -188,13 +185,13 @@
       if (mount_info->user_visible)
 	g_warning (G_STRLOC ": An unknown mount was removed!");
       
-      G_UNLOCK (_the_daemon_volume_monitor);
+      G_UNLOCK (daemon_vm);
       return;
     }
 
   daemon_monitor->mounts = g_list_remove (daemon_monitor->mounts, mount);
   
-  G_UNLOCK (_the_daemon_volume_monitor);
+  G_UNLOCK (daemon_vm);
 
   g_signal_emit_by_name (daemon_monitor, "mount_removed", mount);
   g_signal_emit_by_name (mount, "unmounted");
@@ -244,8 +241,6 @@
 {
   GDaemonVolumeMonitor *monitor;
   
-  G_LOCK (_the_daemon_volume_monitor);
-
   monitor = G_DAEMON_VOLUME_MONITOR (object);
 
   g_signal_handlers_disconnect_by_func (monitor->mount_tracker, mount_added, monitor);
@@ -258,10 +253,21 @@
   
   if (G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->finalize) (object);
+}
 
-  _the_daemon_volume_monitor = NULL;
+static void
+g_daemon_volume_monitor_dispose (GObject *object)
+{
+  GDaemonVolumeMonitor *monitor;
+  
+  monitor = G_DAEMON_VOLUME_MONITOR (object);
 
-  G_UNLOCK (_the_daemon_volume_monitor);
+  G_LOCK (daemon_vm);
+  _the_daemon_volume_monitor = NULL;
+  G_UNLOCK (daemon_vm);
+  
+  if (G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->dispose)
+    (*G_OBJECT_CLASS (g_daemon_volume_monitor_parent_class)->dispose) (object);
 }
 
 static void
@@ -293,6 +299,7 @@
   GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
   
   gobject_class->finalize = g_daemon_volume_monitor_finalize;
+  gobject_class->dispose = g_daemon_volume_monitor_dispose;
 
   monitor_class->is_supported = is_supported;
   monitor_class->get_mounts = get_mounts;

Modified: trunk/hal/ghaldrive.c
==============================================================================
--- trunk/hal/ghaldrive.c	(original)
+++ trunk/hal/ghaldrive.c	Tue Mar  4 11:20:26 2008
@@ -35,6 +35,8 @@
 #include "ghaldrive.h"
 #include "ghalvolume.h"
 
+/* Protects all fields of GHalDrive that can change */
+G_LOCK_DEFINE_STATIC(hal_drive);
 
 struct _GHalDrive {
   GObject parent;
@@ -246,13 +248,10 @@
   icon_from_hal = hal_device_get_property_string (d, "info.desktop.icon");
 
   if (strlen (icon_from_hal) > 0)
-    {
-      s = g_strdup (icon_from_hal);
-    }
+    s = g_strdup (icon_from_hal);
   else if (is_audio_player)
-    {
-      s = g_strdup ("multimedia-player");
-  } else if (strcmp (drive_type, "disk") == 0)
+    s = g_strdup ("multimedia-player");
+  else if (strcmp (drive_type, "disk") == 0)
     {
       if (strcmp (drive_bus, "ide") == 0)
         s = g_strdup ("drive-removable-media-ata");
@@ -315,6 +314,19 @@
     }
 }
 
+static gboolean
+changed_in_idle (gpointer data)
+{
+  GHalDrive *drive = data;
+  
+  g_signal_emit_by_name (drive, "changed");
+  if (drive->volume_monitor != NULL)
+    g_signal_emit_by_name (drive->volume_monitor, "drive_changed", drive);
+  g_object_unref (drive);
+  
+  return FALSE;
+}
+
 static void
 _update_from_hal (GHalDrive *d, gboolean emit_changed)
 {
@@ -326,6 +338,8 @@
   gboolean old_can_poll_for_media;
   gboolean old_can_eject;
 
+  G_LOCK (hal_drive);
+  
   old_name = g_strdup (d->name);
   old_icon = g_strdup (d->icon);
   old_uses_removable_media = d->uses_removable_media;
@@ -338,25 +352,22 @@
   g_free (d->icon);
   _do_update_from_hal (d);
 
-  if (emit_changed)
-    {
-      if (old_uses_removable_media != d->uses_removable_media ||
-          old_has_media != d->has_media ||
-          old_is_media_check_automatic != d->is_media_check_automatic ||
-          old_can_poll_for_media != d->can_poll_for_media ||
-          old_can_eject != d->can_eject ||
-          old_name == NULL || 
-          old_icon == NULL ||
-          strcmp (old_name, d->name) != 0 ||
-          strcmp (old_icon, d->icon) != 0)
-        {
-          g_signal_emit_by_name (d, "changed");
-          if (d->volume_monitor != NULL)
-            g_signal_emit_by_name (d->volume_monitor, "drive_changed", d);
-        }
-    }
+  if (emit_changed &&
+      (old_uses_removable_media != d->uses_removable_media ||
+       old_has_media != d->has_media ||
+       old_is_media_check_automatic != d->is_media_check_automatic ||
+       old_can_poll_for_media != d->can_poll_for_media ||
+       old_can_eject != d->can_eject ||
+       old_name == NULL || 
+       old_icon == NULL ||
+       strcmp (old_name, d->name) != 0 ||
+       strcmp (old_icon, d->icon) != 0))
+      g_idle_add (changed_in_idle, g_object_ref (d));
+  
   g_free (old_name);
   g_free (old_icon);
+
+  G_UNLOCK (hal_drive);
 }
 
 static void
@@ -405,69 +416,93 @@
 void 
 g_hal_drive_disconnected (GHalDrive *drive)
 {
-  GList *l;
+  GList *l, *volumes;
 
-  for (l = drive->volumes; l != NULL; l = l->next)
+  G_LOCK (hal_drive);
+  volumes = drive->volumes;
+  drive->volumes = NULL;
+  G_UNLOCK (hal_drive);
+  
+  for (l = volumes; l != NULL; l = l->next)
     {
       GHalVolume *volume = l->data;
       g_hal_volume_unset_drive (volume, drive);
     }
+
+  g_list_free (volumes);
 }
 
 void 
 g_hal_drive_set_volume (GHalDrive *drive, 
-                         GHalVolume *volume)
+                        GHalVolume *volume)
 {
 
-  if (g_list_find (drive->volumes, volume) != NULL)
-    return;
-
-  drive->volumes = g_list_prepend (drive->volumes, volume);
+  G_LOCK (hal_drive);
   
-  /* TODO: Emit changed in idle to avoid locking issues */
-  g_signal_emit_by_name (drive, "changed");
-  if (drive->volume_monitor != NULL)
-    g_signal_emit_by_name (drive->volume_monitor, "drive_changed", drive);
+  if (g_list_find (drive->volumes, volume) == NULL)
+    {
+      drive->volumes = g_list_prepend (drive->volumes, volume);
+      g_idle_add (changed_in_idle, g_object_ref (drive));
+    }
+
+  G_UNLOCK (hal_drive);
 }
 
 void 
 g_hal_drive_unset_volume (GHalDrive *drive, 
-                           GHalVolume *volume)
+                          GHalVolume *volume)
 {
   GList *l;
 
+  G_LOCK (hal_drive);
+  
   l = g_list_find (drive->volumes, volume);
   if (l != NULL)
     {
       drive->volumes = g_list_delete_link (drive->volumes, l);
 
-      /* TODO: Emit changed in idle to avoid locking issues */
-      g_signal_emit_by_name (drive, "changed");
-      if (drive->volume_monitor != NULL)
-        g_signal_emit_by_name (drive->volume_monitor, "drive_changed", drive);
+      g_idle_add (changed_in_idle, g_object_ref (drive));
     }
+  
+  G_UNLOCK (hal_drive);
 }
 
 gboolean 
 g_hal_drive_has_udi (GHalDrive *drive, const char *udi)
 {
-  return strcmp (udi, hal_device_get_udi (drive->device)) == 0;
+  gboolean res;
+  
+  G_LOCK (hal_drive);
+  res = strcmp (udi, hal_device_get_udi (drive->device)) == 0;
+  G_UNLOCK (hal_drive);
+
+  return res;
 }
 
 static GIcon *
 g_hal_drive_get_icon (GDrive *drive)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+  GIcon *icon;
 
-  return g_themed_icon_new_with_default_fallbacks (hal_drive->icon);
+  G_LOCK (hal_drive);
+  icon = g_themed_icon_new_with_default_fallbacks (hal_drive->icon);
+  G_UNLOCK (hal_drive);
+  
+  return icon; 
 }
 
 static char *
 g_hal_drive_get_name (GDrive *drive)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+  char *name;
+
+  G_LOCK (hal_drive);
+  name = g_strdup (hal_drive->name);
+  G_UNLOCK (hal_drive);
   
-  return g_strdup (hal_drive->name);
+  return name;
 }
 
 static GList *
@@ -476,8 +511,10 @@
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
   GList *l;
 
+  G_LOCK (hal_drive);
   l = g_list_copy (hal_drive->volumes);
   g_list_foreach (l, (GFunc) g_object_ref, NULL);
+  G_UNLOCK (hal_drive);
 
   return l;
 }
@@ -486,44 +523,79 @@
 g_hal_drive_has_volumes (GDrive *drive)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
-  return g_list_length (hal_drive->volumes) > 0;
+  gboolean res;
+
+  G_LOCK (hal_drive);
+  res = hal_drive->volumes != NULL;
+  G_UNLOCK (hal_drive);
+  
+  return res;
 }
 
 static gboolean
 g_hal_drive_is_media_removable (GDrive *drive)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
-  return hal_drive->uses_removable_media;
+  gboolean res;
+
+  G_LOCK (hal_drive);
+  res = hal_drive->uses_removable_media;
+  G_UNLOCK (hal_drive);
+  
+  return res;
 }
 
 static gboolean
 g_hal_drive_has_media (GDrive *drive)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
-  return hal_drive->has_media;
+  gboolean res;
+
+  G_LOCK (hal_drive);
+  res = hal_drive->has_media;
+  G_UNLOCK (hal_drive);
+  
+  return res;
 }
 
 static gboolean
 g_hal_drive_is_media_check_automatic (GDrive *drive)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
-  return hal_drive->is_media_check_automatic;
+  gboolean res;
+
+  G_LOCK (hal_drive);
+  res = hal_drive->is_media_check_automatic;
+  G_UNLOCK (hal_drive);
+  
+  return res;
 }
 
 static gboolean
 g_hal_drive_can_eject (GDrive *drive)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
-  return hal_drive->can_eject;
+  gboolean res;
+  
+  G_LOCK (hal_drive);
+  res = hal_drive->can_eject;
+  G_UNLOCK (hal_drive);
+
+  return res;
 }
 
 static gboolean
 g_hal_drive_can_poll_for_media (GDrive *drive)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
-  return hal_drive->can_poll_for_media;
-}
+  gboolean res;
+  
+  G_LOCK (hal_drive);
+  res = hal_drive->can_poll_for_media;
+  G_UNLOCK (hal_drive);
 
+  return res;
+}
 
 typedef struct {
   GObject *object;
@@ -575,7 +647,9 @@
   GError *error;
   char *argv[] = {"gnome-mount", "-e", "-b", "-d", NULL, NULL};
 
-  argv[4] = hal_drive->device_path;
+  G_LOCK (hal_drive);
+  argv[4] = g_strdup (hal_drive->device_path);
+  G_UNLOCK (hal_drive);
   
   data = g_new0 (SpawnOp, 1);
   data->object = G_OBJECT (drive);
@@ -591,20 +665,23 @@
                       NULL,         /* child_setup */
                       NULL,         /* user_data for child_setup */
                       &child_pid,
-                      &error)) {
-    GSimpleAsyncResult *simple;
-    simple = g_simple_async_result_new_from_error (data->object,
-                                                   data->callback,
-                                                   data->user_data,
-                                                   error);
-    g_simple_async_result_complete (simple);
-    g_object_unref (simple);
-    g_error_free (error);
-    g_free (data);
-    return;
-  }
-  
-  g_child_watch_add (child_pid, spawn_cb, data);
+                      &error))
+    {
+      GSimpleAsyncResult *simple;
+      
+      simple = g_simple_async_result_new_from_error (data->object,
+                                                     data->callback,
+                                                     data->user_data,
+                                                     error);
+      g_simple_async_result_complete (simple);
+      g_object_unref (simple);
+      g_error_free (error);
+      g_free (data);
+    }
+  else
+    g_child_watch_add (child_pid, spawn_cb, data);
+    
+  g_free (argv[4]);
 }
 
 
@@ -727,6 +804,7 @@
   data->user_data = user_data;
   data->flags = flags;
 
+  G_LOCK (hal_drive);
   for (l = hal_drive->volumes; l != NULL; l = l->next)
     {
       GHalVolume *volume = l->data;
@@ -736,6 +814,7 @@
       if (mount != NULL && g_mount_can_unmount (mount))
         data->pending_mounts = g_list_prepend (data->pending_mounts, g_object_ref (mount));
     }
+  G_UNLOCK (hal_drive);
 
   _eject_unmount_mounts (data);
 }
@@ -821,13 +900,14 @@
   data->cancellable = cancellable;
 
   /*g_warning ("Rescanning udi %s", hal_device_get_udi (hal_drive->device));*/
-  
+
+  G_LOCK (hal_drive);
   con = hal_pool_get_dbus_connection (hal_drive->pool);
-  
   msg = dbus_message_new_method_call ("org.freedesktop.Hal", 
                                       hal_device_get_udi (hal_drive->device),
                                       "org.freedesktop.Hal.Device.Storage.Removable",
                                       "CheckForMedia");
+  G_UNLOCK (hal_drive);
   
   if (!dbus_connection_send_with_reply (con, msg, &pending_call, -1))
     {
@@ -844,13 +924,14 @@
       g_object_unref (simple);
       g_error_free (error);
       g_free (data);
-      return;
     }
-
-  dbus_pending_call_set_notify (pending_call,
-                                poll_for_media_cb,
-                                data,
-                                (DBusFreeFunction) g_free);
+  else
+    dbus_pending_call_set_notify (pending_call,
+                                  poll_for_media_cb,
+                                  data,
+                                  (DBusFreeFunction) g_free);
+  
+  dbus_message_unref (msg);
 }
 
 static gboolean
@@ -867,14 +948,21 @@
                              const char          *kind)
 {
   GHalDrive *hal_drive = G_HAL_DRIVE (drive);
+  char *res;
+
+  res = NULL;
 
+  G_LOCK (hal_drive);
+  
   if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_HAL_UDI) == 0)
-    return g_strdup (hal_device_get_udi (hal_drive->device));
+    res = g_strdup (hal_device_get_udi (hal_drive->device));
   
   if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
-    return g_strdup (hal_drive->device_path);
+    res = g_strdup (hal_drive->device_path);
+  
+  G_UNLOCK (hal_drive);
   
-  return NULL;
+  return res;
 }
 
 static char **
@@ -885,6 +973,8 @@
 
   res = g_ptr_array_new ();
 
+  G_LOCK (hal_drive);
+  
   g_ptr_array_add (res,
                    g_strdup (G_VOLUME_IDENTIFIER_KIND_HAL_UDI));
 
@@ -893,6 +983,8 @@
                      g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE));
     
 
+  G_UNLOCK (hal_drive);
+  
   /* Null-terminate */
   g_ptr_array_add (res, NULL);
   

Modified: trunk/hal/ghalmount.c
==============================================================================
--- trunk/hal/ghalmount.c	(original)
+++ trunk/hal/ghalmount.c	Tue Mar  4 11:20:26 2008
@@ -36,6 +36,9 @@
 #include "ghalmount.h"
 #include "ghalvolume.h"
 
+/* Protects all fields of GHalDrive that can change */
+G_LOCK_DEFINE_STATIC(hal_mount);
+
 struct _GHalMount {
   GObject parent;
 
@@ -138,6 +141,19 @@
 {
 }
 
+static gboolean
+changed_in_idle (gpointer data)
+{
+  GHalMount *mount = data;
+  
+  g_signal_emit_by_name (mount, "changed");
+  if (mount->volume_monitor != NULL)
+    g_signal_emit_by_name (mount->volume_monitor, "mount_changed", mount);
+  g_object_unref (mount);
+  
+  return FALSE;
+}
+
 static const struct {
   const char *disc_type;
   const char *icon_name;
@@ -409,34 +425,23 @@
   is_crypto = FALSE;
   is_crypto_cleartext = FALSE;
   if (strcmp (hal_device_get_property_string (volume, "volume.fsusage"), "crypto") == 0)
-    {
       is_crypto = TRUE;
-    }
+
   if (strlen (hal_device_get_property_string (volume, "volume.crypto_luks.clear.backing_volume")) > 0)
-    {
       is_crypto_cleartext = TRUE;
-    }
 
   /*g_warning ("drive_type='%s'", drive_type); */
   /*g_warning ("drive_bus='%s'", drive_bus); */
   /*g_warning ("drive_uses_removable_media=%d", drive_uses_removable_media); */
 
   if (strlen (volume_icon_from_hal) > 0)
-    {
-      icon_name = volume_icon_from_hal;
-    }
+    icon_name = volume_icon_from_hal;
   else if (strlen (icon_from_hal) > 0)
-    {
-      icon_name = icon_from_hal;
-    }
+    icon_name = icon_from_hal;
   else if (is_audio_player)
-    {
-      icon_name = "multimedia-player";
-    }
+    icon_name = "multimedia-player";
   else if (is_crypto || is_crypto_cleartext)
-    {
-      icon_name = "media-encrypted";
-    }
+    icon_name = "media-encrypted";
   else if (strcmp (drive_type, "disk") == 0)
     {
       if (strcmp (drive_bus, "ide") == 0)
@@ -469,13 +474,9 @@
 
   
   if (strlen (volume_name_from_hal) > 0)
-    {
-      name = g_strdup (volume_name_from_hal);
-    }
+    name = g_strdup (volume_name_from_hal);
   else if (strlen (name_from_hal) > 0)
-    {
-      name = g_strdup (name_from_hal);
-    }
+    name = g_strdup (name_from_hal);
   else if (volume_fs_label != NULL && strlen (volume_fs_label) > 0)
     name = g_strdup (volume_fs_label);
   else if (volume_is_disc)
@@ -520,6 +521,8 @@
   char *old_name;
   GIcon *old_icon;
 
+  G_LOCK (hal_mount);
+  
   old_name = g_strdup (m->name);
   old_icon = m->icon != NULL ? g_object_ref (m->icon) : NULL;
 
@@ -534,15 +537,13 @@
           old_icon == NULL ||
           strcmp (old_name, m->name) != 0 ||
           (! g_icon_equal (old_icon, m->icon)))
-        {
-          g_signal_emit_by_name (m, "changed");
-          if (m->volume_monitor != NULL)
-            g_signal_emit_by_name (m->volume_monitor, "mount_changed", m);
-        }
+        g_idle_add (changed_in_idle, g_object_ref (m));
     }
   g_free (old_name);
   if (old_icon != NULL)
     g_object_unref (old_icon);
+
+  G_UNLOCK (hal_mount);
 }
 
 static void
@@ -635,12 +636,16 @@
 void 
 g_hal_mount_override_name (GHalMount *mount, const char *name)
 {
+  G_LOCK (hal_mount);
+  
   g_free (mount->override_name);
 
   if (name != NULL)
     mount->override_name = g_strdup (name);
   else
     mount->override_name = NULL;
+  
+  G_UNLOCK (hal_mount);
 
   update_from_hal (mount, TRUE);
 }
@@ -648,6 +653,7 @@
 void
 g_hal_mount_override_icon (GHalMount *mount, GIcon *icon)
 {
+  G_LOCK (hal_mount);
   if (mount->override_icon != NULL)
     g_object_unref (mount->override_icon);
 
@@ -656,6 +662,8 @@
   else
     mount->override_icon = NULL;
 
+  G_UNLOCK (hal_mount);
+  
   update_from_hal (mount, TRUE);
 }
 
@@ -743,121 +751,171 @@
 void
 g_hal_mount_unmounted (GHalMount *mount)
 {
+  G_LOCK (hal_mount);
   if (mount->volume != NULL)
     {
       g_hal_volume_unset_mount (mount->volume, mount);
       mount->volume = NULL;
-      g_signal_emit_by_name (mount, "changed");
-      /* there's really no need to emit volume_changed on the volume monitor 
-       * as we're going to be deleted.. */
+      g_idle_add (changed_in_idle, g_object_ref (mount));
     }
+  G_UNLOCK (hal_mount);
 }
 
 void
 g_hal_mount_unset_volume (GHalMount *mount,
                                        GHalVolume  *volume)
 {
+  G_LOCK (hal_mount);
   if (mount->volume == volume)
     {
       mount->volume = NULL;
-      /* TODO: Emit changed in idle to avoid locking issues */
-      g_signal_emit_by_name (mount, "changed");
-      if (mount->volume_monitor != NULL)
-        g_signal_emit_by_name (mount->volume_monitor, "mount_changed", mount);
+      g_idle_add (changed_in_idle, g_object_ref (mount));
     }
+  G_UNLOCK (hal_mount);
 }
 
 static GFile *
 g_hal_mount_get_root (GMount *mount)
 {
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
+  GFile *root;
 
+  G_LOCK (hal_mount);
+  
   if (hal_mount->override_root != NULL)
-    return g_object_ref (hal_mount->override_root);
+    root = g_object_ref (hal_mount->override_root);
   else
-    return g_file_new_for_path (hal_mount->mount_path);
+    root = g_file_new_for_path (hal_mount->mount_path);
+
+  G_UNLOCK (hal_mount);
+
+  return root;
 }
 
 static GIcon *
 g_hal_mount_get_icon (GMount *mount)
 {
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
+  GIcon *icon;
 
-  return g_object_ref (hal_mount->icon);
+  G_LOCK (hal_mount);
+  icon = g_object_ref (hal_mount->icon);
+  G_UNLOCK (hal_mount);
+  
+  return icon;
 }
 
 static char *
 g_hal_mount_get_uuid (GMount *mount)
 {
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
+  char *uuid;
 
-  return g_strdup (hal_mount->uuid);
+  G_LOCK (hal_mount);
+  uuid = g_strdup (hal_mount->uuid);
+  G_UNLOCK (hal_mount);
+  
+  return uuid;
 }
 
 static char *
 g_hal_mount_get_name (GMount *mount)
 {
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
+  char *name;
+
+  G_LOCK (hal_mount);
+  name = g_strdup (hal_mount->name);
+  G_UNLOCK (hal_mount);
   
-  return g_strdup (hal_mount->name);
+  return name;
 }
 
 gboolean
 g_hal_mount_has_uuid (GHalMount         *mount,
                        const char        *uuid)
 {
-  if (mount->uuid == NULL)
-    return FALSE;
-  return strcmp (mount->uuid, uuid) == 0;
+  gboolean res;
+
+  G_LOCK (hal_mount);
+  res = FALSE;
+  if (mount->uuid != NULL)
+    res = strcmp (mount->uuid, uuid) == 0;
+  G_UNLOCK (hal_mount);
+
+  return res;
 }
 
 gboolean
 g_hal_mount_has_mount_path (GHalMount *mount,
                             const char  *mount_path)
 {
-  return strcmp (mount->mount_path, mount_path) == 0;
+  gboolean res;
+
+  G_LOCK (hal_mount);
+  res = strcmp (mount->mount_path, mount_path) == 0;
+  G_UNLOCK (hal_mount);
+  return res;
 }
 
 gboolean
 g_hal_mount_has_udi (GHalMount *mount,
                      const char  *udi)
 {
-  if (mount->device == NULL)
-    return FALSE;
-  return strcmp (hal_device_get_udi (mount->device), udi) == 0;
+  gboolean res;
+
+  G_LOCK (hal_mount);
+  res = FALSE;
+  if (mount->device != NULL)
+    res = strcmp (hal_device_get_udi (mount->device), udi) == 0;
+  G_UNLOCK (hal_mount);
+
+  return res;
 }
 
 static GDrive *
 g_hal_mount_get_drive (GMount *mount)
 {
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
+  GDrive *drive;
 
+  G_LOCK (hal_mount);
+  drive = NULL;
   if (hal_mount->volume != NULL)
-    return g_volume_get_drive (G_VOLUME (hal_mount->volume));
+    drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
+  G_UNLOCK (hal_mount);
 
-  return NULL;
+  return drive;
 }
 
 static GVolume *
 g_hal_mount_get_volume (GMount *mount)
 {
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
+  GVolume *volume;
 
+  G_LOCK (hal_mount);
+  volume = NULL;
   if (hal_mount->volume)
-    return G_VOLUME (g_object_ref (hal_mount->volume));
+    volume = G_VOLUME (g_object_ref (hal_mount->volume));
+  G_UNLOCK (hal_mount);
   
-  return NULL;
+  return volume;
 }
 
 static gboolean
 g_hal_mount_can_unmount (GMount *mount)
 {
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
+  gboolean res;
 
+  G_LOCK (hal_mount);
+  res = TRUE;
   if (hal_mount->cannot_unmount)
-    return FALSE;
+    res = FALSE;
+  G_UNLOCK (hal_mount);
 
-  return TRUE;
+  return res;
 }
 
 static gboolean
@@ -867,19 +925,19 @@
   GDrive *drive;
   gboolean can_eject;
 
+  G_LOCK (hal_mount);
   can_eject = FALSE;
-
   if (hal_mount->volume != NULL)
     {
       drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
       if (drive != NULL)
         can_eject = g_drive_can_eject (drive);
     }
+  G_UNLOCK (hal_mount);
 
   return can_eject;
 }
 
-
 typedef struct {
   GObject *object;
   GAsyncReadyCallback callback;
@@ -1019,18 +1077,27 @@
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
   char *argv[] = {"gnome-mount", "-u", "-b", "-d", NULL, NULL};
   gboolean using_legacy = FALSE;
+  char *d, *m;
 
+  G_LOCK (hal_mount);
+  d = g_strdup (hal_mount->device_path);
+  m = g_strdup (hal_mount->mount_path);
+  G_UNLOCK (hal_mount);
+
+  
   if (hal_mount->device != NULL)
-    argv[4] = hal_mount->device_path;
+    argv[4] = d;
   else
     {
       using_legacy = TRUE;
       argv[0] = "umount";
-      argv[1] = hal_mount->mount_path;
+      argv[1] = m;
       argv[2] = NULL;
     }
 
   unmount_do (mount, cancellable, callback, user_data, argv, using_legacy);
+  g_free (d);
+  g_free (m);
 }
 
 static gboolean
@@ -1067,18 +1134,21 @@
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
   GDrive *drive;
 
+  G_LOCK (hal_mount);
+  drive = NULL;
   if (hal_mount->volume != NULL)
+    drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
+  G_UNLOCK (hal_mount);
+  
+  if (drive != NULL)
     {
-      drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
-      if (drive != NULL)
-        {
-          EjectWrapperOp *data;
-          data = g_new0 (EjectWrapperOp, 1);
-          data->object = G_OBJECT (mount);
-          data->callback = callback;
-          data->user_data = user_data;
-          g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
-        }
+      EjectWrapperOp *data;
+      data = g_new0 (EjectWrapperOp, 1);
+      data->object = G_OBJECT (mount);
+      data->callback = callback;
+      data->user_data = user_data;
+      g_drive_eject (drive, flags, cancellable, eject_wrapper_callback, data);
+      g_object_unref (drive);
     }
 }
 
@@ -1089,14 +1159,22 @@
 {
   GHalMount *hal_mount = G_HAL_MOUNT (mount);
   GDrive *drive;
+  gboolean res;
 
+  res = TRUE;
+  
+  G_LOCK (hal_mount);
+  drive = NULL;
   if (hal_mount->volume != NULL)
+    drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
+  G_UNLOCK (hal_mount);
+  
+  if (drive != NULL)
     {
-      drive = g_volume_get_drive (G_VOLUME (hal_mount->volume));
-      if (drive != NULL)
-        return g_drive_eject_finish (drive, result, error);
+      res = g_drive_eject_finish (drive, result, error);
+      g_object_unref (drive);
     }
-  return TRUE;
+  return res;
 }
 
 static void

Modified: trunk/hal/ghalvolume.c
==============================================================================
--- trunk/hal/ghalvolume.c	(original)
+++ trunk/hal/ghalvolume.c	Tue Mar  4 11:20:26 2008
@@ -36,6 +36,9 @@
 #include "ghalvolume.h"
 #include "ghalmount.h"
 
+/* Protects all fields of GHalDrive that can change */
+G_LOCK_DEFINE_STATIC(hal_volume);
+
 struct _GHalVolume {
   GObject parent;
 
@@ -130,6 +133,19 @@
 {
 }
 
+static gboolean
+changed_in_idle (gpointer data)
+{
+  GHalVolume *volume = data;
+  
+  g_signal_emit_by_name (volume, "changed");
+  if (volume->volume_monitor != NULL)
+    g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+  g_object_unref (volume);
+  
+  return FALSE;
+}
+
 static const struct {
   const char *disc_type;
   const char *icon_name;
@@ -274,13 +290,9 @@
   is_crypto = FALSE;
   is_crypto_cleartext = FALSE;
   if (strcmp (hal_device_get_property_string (volume, "volume.fsusage"), "crypto") == 0)
-    {
-      is_crypto = TRUE;
-    }
+    is_crypto = TRUE;
   if (strlen (hal_device_get_property_string (volume, "volume.crypto_luks.clear.backing_volume")) > 0)
-    {
-      is_crypto_cleartext = TRUE;
-    }
+    is_crypto_cleartext = TRUE;
 
   if (volume_is_disc && volume_disc_has_audio && mv->foreign_mount_root != NULL)
     name = g_strdup (_("Audio Disc"));
@@ -363,9 +375,7 @@
 
   v->name = NULL;
   if (strlen (name_from_hal) > 0)
-    {
-      v->name = g_strdup (name_from_hal);
-    }
+    v->name = g_strdup (name_from_hal);
   else if (vendor == NULL)
     {
       if (product != NULL)
@@ -374,9 +384,7 @@
   else
     {
       if (product != NULL)
-        {
-          v->name = g_strdup_printf ("%s %s", vendor, product);
-        }
+        v->name = g_strdup_printf ("%s %s", vendor, product);
       else
         {
           if (is_audio_player)
@@ -394,27 +402,17 @@
   if (v->name == NULL)
     {
       if (is_audio_player)
-        {
-          v->name = g_strdup (_("Audio Player"));
-        }
+        v->name = g_strdup (_("Audio Player"));
       else
-        {
-          v->name = g_strdup (_("Camera"));
-        }
+        v->name = g_strdup (_("Camera"));
     }
 
   if (strlen (icon_from_hal) > 0)
-    {
-      v->icon = g_strdup (icon_from_hal);
-    }
+    v->icon = g_strdup (icon_from_hal);
   else if (is_audio_player)
-    {
-      v->icon = g_strdup ("multimedia-player");
-    }
+    v->icon = g_strdup ("multimedia-player");
   else
-    {
-      v->icon = g_strdup ("camera");
-    }
+    v->icon = g_strdup ("camera");
   v->mount_path = NULL;
 
   g_object_set_data_full (G_OBJECT (v), 
@@ -431,6 +429,8 @@
   char *old_icon;
   char *old_mount_path;
 
+  G_LOCK (hal_volume);
+  
   old_name = g_strdup (mv->name);
   old_icon = g_strdup (mv->icon);
   old_mount_path = g_strdup (mv->mount_path);
@@ -465,15 +465,13 @@
            old_icon == NULL ||
            strcmp (old_name, mv->name) != 0 ||
            strcmp (old_icon, mv->icon) != 0))
-        {
-          g_signal_emit_by_name (mv, "changed");
-          if (mv->volume_monitor != NULL)
-            g_signal_emit_by_name (mv->volume_monitor, "volume_changed", mv);
-        }
+        g_idle_add (changed_in_idle, g_object_ref (mv));
     }
   g_free (old_name);
   g_free (old_icon);
   g_free (old_mount_path);
+
+  G_UNLOCK (hal_volume);
 }
 
 static void
@@ -589,13 +587,16 @@
 }
 
 /**
- * g_hal_volume_disconnected:
+ * g_hal_volume_removed:
  * @volume:
  * 
  **/
 void
 g_hal_volume_removed (GHalVolume *volume)
 {
+
+  G_LOCK (hal_volume);
+  
   if (volume->mount != NULL)
     {
       g_hal_mount_unset_volume (volume->mount, volume);
@@ -607,155 +608,210 @@
       g_hal_drive_unset_volume (volume->drive, volume);
       volume->drive = NULL;
     }
+
+  G_UNLOCK (hal_volume);
 }
 
 void
 g_hal_volume_set_mount (GHalVolume  *volume,
                         GHalMount *mount)
 {
-  if (volume->mount == mount)
-    return;
-  
-  if (volume->mount != NULL)
-    g_hal_mount_unset_volume (volume->mount, volume);
-  
-  volume->mount = mount;
-  
-  /* TODO: Emit changed in idle to avoid locking issues */
-  g_signal_emit_by_name (volume, "changed");
-  if (volume->volume_monitor != NULL)
-    g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+  G_LOCK (hal_volume);
+  if (volume->mount != mount)
+    {
+      
+      if (volume->mount != NULL)
+        g_hal_mount_unset_volume (volume->mount, volume);
+      
+      volume->mount = mount;
+
+      g_idle_add (changed_in_idle, g_object_ref (volume));
+    }
+  G_UNLOCK (hal_volume);
 }
  
 void
 g_hal_volume_unset_mount (GHalVolume  *volume,
                           GHalMount *mount)
 {
+  G_LOCK (hal_volume);
   if (volume->mount == mount)
     {
       volume->mount = NULL;
-      /* TODO: Emit changed in idle to avoid locking issues */
-      g_signal_emit_by_name (volume, "changed");
-      if (volume->volume_monitor != NULL)
-        g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+      g_idle_add (changed_in_idle, g_object_ref (volume));
     }
+  G_UNLOCK (hal_volume);
 }
 
 void
 g_hal_volume_set_drive (GHalVolume  *volume,
                         GHalDrive *drive)
 {
-  if (volume->drive == drive)
-    return;
-  
-  if (volume->drive != NULL)
-    g_hal_drive_unset_volume (volume->drive, volume);
-  
-  volume->drive = drive;
-  
-  /* TODO: Emit changed in idle to avoid locking issues */
-  g_signal_emit_by_name (volume, "changed");
-  if (volume->volume_monitor != NULL)
-    g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+  G_LOCK (hal_volume);
+  if (volume->drive != drive)
+    {
+      if (volume->drive != NULL)
+        g_hal_drive_unset_volume (volume->drive, volume);
+      
+      volume->drive = drive;
+      
+      g_idle_add (changed_in_idle, g_object_ref (volume));
+    }
+  G_UNLOCK (hal_volume);
 }
 
 void
 g_hal_volume_unset_drive (GHalVolume  *volume,
                           GHalDrive *drive)
 {
+  G_LOCK (hal_volume);
   if (volume->drive == drive)
     {
       volume->drive = NULL;
-      /* TODO: Emit changed in idle to avoid locking issues */
-      g_signal_emit_by_name (volume, "changed");
-      if (volume->volume_monitor != NULL)
-        g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+      g_idle_add (changed_in_idle, g_object_ref (volume));
     }
+  G_UNLOCK (hal_volume);
 }
 
 static GIcon *
 g_hal_volume_get_icon (GVolume *volume)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
-  return g_themed_icon_new_with_default_fallbacks (hal_volume->icon);
+  GIcon *icon;
+
+  G_LOCK (hal_volume);
+  icon = g_themed_icon_new_with_default_fallbacks (hal_volume->icon);
+  G_UNLOCK (hal_volume);
+  
+  return icon;
 }
 
 static char *
 g_hal_volume_get_name (GVolume *volume)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
-  return g_strdup (hal_volume->name);
+  char *name;
+
+  G_LOCK (hal_volume);
+  name = g_strdup (hal_volume->name);
+  G_UNLOCK (hal_volume);
+  
+  return name;
 }
 
 static char *
 g_hal_volume_get_uuid (GVolume *volume)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
-  return g_strdup (hal_volume->uuid);
+  char *uuid;
+
+  G_LOCK (hal_volume);
+  uuid = g_strdup (hal_volume->uuid);
+  G_UNLOCK (hal_volume);
+  
+  return uuid;
 }
 
 static gboolean
 g_hal_volume_can_mount (GVolume *volume)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
-  return hal_volume->is_mountable;
+  gboolean res;
+
+  G_LOCK (hal_volume);
+  res = hal_volume->is_mountable;
+  G_UNLOCK (hal_volume);
+  
+  return res;
 }
 
 static gboolean
 g_hal_volume_can_eject (GVolume *volume)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  gboolean res;
+
+  G_LOCK (hal_volume);
+  res = FALSE;
   if (hal_volume->drive != NULL)
-    return g_drive_can_eject (G_DRIVE (hal_volume->drive));
-  return FALSE;
+    res = g_drive_can_eject (G_DRIVE (hal_volume->drive));
+  G_UNLOCK (hal_volume);
+  
+  return res;
 }
 
 static gboolean
 g_hal_volume_should_automount (GVolume *volume)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
-  return ! (hal_volume->ignore_automount);
+  gboolean res;
+
+  G_LOCK (hal_volume);
+  res = ! (hal_volume->ignore_automount);
+  G_UNLOCK (hal_volume);
+  
+  return res;
 }
 
 static GDrive *
 g_hal_volume_get_drive (GVolume *volume)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  GDrive *drive;
+
+  G_LOCK (hal_volume);
+  drive = NULL;
   if (hal_volume->drive != NULL)
-    return g_object_ref (hal_volume->drive);
-  return NULL;
+    drive = g_object_ref (hal_volume->drive);
+  G_UNLOCK (hal_volume);
+  
+  return drive;
 }
 
 static GMount *
 g_hal_volume_get_mount (GVolume *volume)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  GMount *mount;
 
+  G_LOCK (hal_volume);
+  mount = NULL;
   if (hal_volume->foreign_mount != NULL)
-    return g_object_ref (hal_volume->foreign_mount);
+    mount = g_object_ref (hal_volume->foreign_mount);
+  else if (hal_volume->mount != NULL)
+    mount = g_object_ref (hal_volume->mount);
+  G_UNLOCK (hal_volume);
 
-  if (hal_volume->mount != NULL)
-    return g_object_ref (hal_volume->mount);
-
-  return NULL;
+  return mount;
 }
 
 gboolean
 g_hal_volume_has_mount_path (GHalVolume *volume,
                              const char  *mount_path)
 {
+  gboolean res;
+
+  G_LOCK (hal_volume);
+  res = FALSE;
   if (volume->mount_path != NULL)
-    return strcmp (volume->mount_path, mount_path) == 0;
-  return FALSE;
+    res = strcmp (volume->mount_path, mount_path) == 0;
+  G_UNLOCK (hal_volume);
+
+  return res;
 }
 
 gboolean
 g_hal_volume_has_device_path (GHalVolume *volume,
                               const char  *device_path)
 {
+  gboolean res;
+
+  res = FALSE;
+  G_LOCK (hal_volume);
   if (volume->device_path != NULL)
-    return strcmp (volume->device_path, device_path) == 0;
-  return FALSE;
+    res = strcmp (volume->device_path, device_path) == 0;
+  G_UNLOCK (hal_volume);
+  return res;
 }
 
 gboolean
@@ -763,9 +819,14 @@
                       const char  *udi)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  gboolean res;
+  
+  G_LOCK (hal_volume);
+  res = FALSE;
   if (hal_volume->device != NULL)
-    return strcmp (hal_device_get_udi (hal_volume->device), udi) == 0;
-  return FALSE;
+    res = strcmp (hal_device_get_udi (hal_volume->device), udi) == 0;
+  G_UNLOCK (hal_volume);
+  return res;
 }
 
 gboolean
@@ -773,22 +834,34 @@
                        const char  *uuid)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  gboolean res;
+
+  G_LOCK (hal_volume);
+  res = FALSE;
   if (hal_volume->uuid != NULL)
-    return strcmp (hal_volume->uuid, uuid) == 0;
-  return FALSE;
+    res = strcmp (hal_volume->uuid, uuid) == 0;
+  G_UNLOCK (hal_volume);
+
+  return res;
 }
 
 static void
 foreign_mount_unmounted (GMount *mount, gpointer user_data)
 {
   GHalVolume *volume = G_HAL_VOLUME (user_data);
-  if (volume->foreign_mount == mount)
+  gboolean check;
+
+  G_LOCK (hal_volume);
+  check = volume->foreign_mount == mount;
+  G_UNLOCK (hal_volume);
+  if (check)
     g_hal_volume_adopt_foreign_mount (volume, NULL);
 }
 
 void
 g_hal_volume_adopt_foreign_mount (GHalVolume *volume, GMount *foreign_mount)
 {
+  G_LOCK (hal_volume);
   if (volume->foreign_mount != NULL)
     g_object_unref (volume->foreign_mount);
 
@@ -800,9 +873,8 @@
   else
     volume->foreign_mount =  NULL;
 
-  g_signal_emit_by_name (volume, "changed");
-  if (volume->volume_monitor != NULL)
-    g_signal_emit_by_name (volume->volume_monitor, "volume_changed", volume);
+  g_idle_add (changed_in_idle, g_object_ref (volume));
+  G_UNLOCK (hal_volume);
 }
 
 gboolean
@@ -810,9 +882,15 @@
                                      GFile            *mount_root)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  gboolean res;
+
+  G_LOCK (hal_volume);
+  res = FALSE;
   if (hal_volume->foreign_mount_root != NULL)
-    return g_file_equal (hal_volume->foreign_mount_root, mount_root);
-  return FALSE;
+    res = g_file_equal (hal_volume->foreign_mount_root, mount_root);
+  G_UNLOCK (hal_volume);
+  
+  return res;
 }
 
 
@@ -935,6 +1013,7 @@
               hal_volume->foreign_mount_root,
               hal_volume->device_path);*/
 
+  G_LOCK (hal_volume);
   if (hal_volume->foreign_mount_root != NULL)
     {
       ForeignMountOp *data;
@@ -960,6 +1039,7 @@
         argv[4] = "-n";
       spawn_do (volume, cancellable, callback, user_data, argv);
     }
+  G_UNLOCK (hal_volume);
 }
 
 static gboolean
@@ -968,11 +1048,17 @@
                            GError       **error)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  gboolean res;
 
+  G_LOCK (hal_volume);
+  res = TRUE;
+  
   if (hal_volume->foreign_mount_root != NULL)
-    return g_file_mount_enclosing_volume_finish (hal_volume->foreign_mount_root, result, error);
+    res = g_file_mount_enclosing_volume_finish (hal_volume->foreign_mount_root, result, error);
+  
+  G_UNLOCK (hal_volume);
   
-  return TRUE;
+  return res;
 }
 
 typedef struct {
@@ -999,17 +1085,25 @@
                     gpointer             user_data)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  GHalDrive *drive;
 
   /*g_warning ("hal_volume_eject");*/
 
+  drive = NULL;
+  G_LOCK (hal_volume);
   if (hal_volume->drive != NULL)
+    drive = g_object_ref (hal_volume->drive);
+  G_UNLOCK (hal_volume);
+  
+  if (drive != NULL)
     {
       EjectWrapperOp *data;
       data = g_new0 (EjectWrapperOp, 1);
       data->object = g_object_ref (volume);
       data->callback = callback;
       data->user_data = user_data;
-      g_drive_eject (G_DRIVE (hal_volume->drive), flags, cancellable, eject_wrapper_callback, data);
+      g_drive_eject (G_DRIVE (drive), flags, cancellable, eject_wrapper_callback, data);
+      g_object_unref (drive);
     }
 }
 
@@ -1019,10 +1113,14 @@
                           GError       **error)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  gboolean res;
 
+  G_LOCK (hal_volume);
+  res = TRUE;
   if (hal_volume->drive != NULL)
-    return g_drive_eject_finish (G_DRIVE (hal_volume->drive), result, error);
-  return TRUE;
+    res = g_drive_eject_finish (G_DRIVE (hal_volume->drive), result, error);
+  G_UNLOCK (hal_volume);
+  return res;
 }
 
 static char *
@@ -1030,20 +1128,21 @@
                              const char          *kind)
 {
   GHalVolume *hal_volume = G_HAL_VOLUME (volume);
+  char *id;
 
+  G_LOCK (hal_volume);
+  id = NULL;
   if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_HAL_UDI) == 0)
-    return g_strdup (hal_device_get_udi (hal_volume->device));
-  
-  if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
-    return g_strdup (hal_volume->device_path);
-  
-  if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_LABEL) == 0)
-    return g_strdup (hal_device_get_property_string (hal_volume->device, "volume.label"));
+    id = g_strdup (hal_device_get_udi (hal_volume->device));
+  else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE) == 0)
+    id = g_strdup (hal_volume->device_path);
+  else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_LABEL) == 0)
+    id = g_strdup (hal_device_get_property_string (hal_volume->device, "volume.label"));
+  else if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0)
+    id = g_strdup (hal_device_get_property_string (hal_volume->device, "volume.uuid"));
+  G_UNLOCK (hal_volume);
   
-  if (strcmp (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0)
-    return g_strdup (hal_device_get_property_string (hal_volume->device, "volume.uuid"));
-  
-  return NULL;
+  return id;
 }
 
 static char **
@@ -1053,6 +1152,8 @@
   GPtrArray *res;
   const char *label, *uuid;
 
+  G_LOCK (hal_volume);
+  
   res = g_ptr_array_new ();
 
   g_ptr_array_add (res,
@@ -1075,6 +1176,8 @@
 
   /* Null-terminate */
   g_ptr_array_add (res, NULL);
+
+  G_UNLOCK (hal_volume);
   
   return (char **)g_ptr_array_free (res, FALSE);
 }

Modified: trunk/hal/ghalvolumemonitor.c
==============================================================================
--- trunk/hal/ghalvolumemonitor.c	(original)
+++ trunk/hal/ghalvolumemonitor.c	Tue Mar  4 11:20:26 2008
@@ -44,6 +44,9 @@
  * We avoid locking since GUnionVolumeMonitor, the only user of us,
  * does locking.
  */
+
+G_LOCK_DEFINE_STATIC(hal_vm);
+
 static GHalVolumeMonitor *the_volume_monitor = NULL;
 static HalPool *pool = NULL;
 
@@ -80,16 +83,37 @@
 static void hal_changed              (HalPool    *pool,
                                       HalDevice  *device,
                                       gpointer    user_data);
-static void update_all               (GHalVolumeMonitor *monitor);
-static void update_drives            (GHalVolumeMonitor *monitor);
-static void update_volumes           (GHalVolumeMonitor *monitor);
-static void update_mounts            (GHalVolumeMonitor *monitor);
-static void update_discs             (GHalVolumeMonitor *monitor);
-static void update_cameras           (GHalVolumeMonitor *monitor);
+static void update_all               (GHalVolumeMonitor *monitor,
+                                      gboolean emit_changes);
+static void update_drives            (GHalVolumeMonitor *monitor,
+                                      GList **added_drives,
+                                      GList **removed_drives);
+static void update_volumes           (GHalVolumeMonitor *monitor,
+                                      GList **added_volumes,
+                                      GList **removed_volumes);
+static void update_mounts            (GHalVolumeMonitor *monitor,
+                                      GList **added_mounts,
+                                      GList **removed_mounts);
+static void update_discs             (GHalVolumeMonitor *monitor,
+                                      GList **added_volumes,
+                                      GList **removed_volumes,
+                                      GList **added_mounts,
+                                      GList **removed_mounts);
+static void update_cameras           (GHalVolumeMonitor *monitor,
+                                      GList **added_volumes,
+                                      GList **removed_volumes);
+
 
 #define g_hal_volume_monitor_get_type g_hal_volume_monitor_get_type
 G_DEFINE_DYNAMIC_TYPE (GHalVolumeMonitor, g_hal_volume_monitor, G_TYPE_NATIVE_VOLUME_MONITOR)
 
+static void
+list_free (GList *objects)
+{
+  g_list_foreach (objects, (GFunc)g_object_unref, NULL);
+  g_list_free (objects);
+}
+
 static HalPool *
 get_hal_pool (void)
 {
@@ -102,11 +126,24 @@
 }
 
 static void
-g_hal_volume_monitor_finalize (GObject *object)
+g_hal_volume_monitor_dispose (GObject *object)
 {
   GHalVolumeMonitor *monitor;
+  
+  monitor = G_HAL_VOLUME_MONITOR (object);
 
+  G_LOCK (hal_vm);
   the_volume_monitor = NULL;
+  G_UNLOCK (hal_vm);
+  
+  if (G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->dispose)
+    (*G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->dispose) (object);
+}
+
+static void
+g_hal_volume_monitor_finalize (GObject *object)
+{
+  GHalVolumeMonitor *monitor;
 
   monitor = G_HAL_VOLUME_MONITOR (object);
 
@@ -116,33 +153,21 @@
 
   g_object_unref (monitor->mount_monitor);
   g_object_unref (monitor->pool);
-
-  g_list_foreach (monitor->last_camera_devices, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->last_camera_devices);
-  g_list_foreach (monitor->last_optical_disc_devices, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->last_optical_disc_devices);
-  g_list_foreach (monitor->last_drive_devices, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->last_drive_devices);
-  g_list_foreach (monitor->last_volume_devices, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->last_volume_devices);
-  g_list_foreach (monitor->last_mountpoints, (GFunc)g_unix_mount_point_free, NULL);
-  g_list_free (monitor->last_mountpoints);
-  g_list_foreach (monitor->last_mounts, (GFunc)g_unix_mount_free, NULL);
-  g_list_free (monitor->last_mounts);
-
-  g_list_foreach (monitor->drives, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->drives);
-  g_list_foreach (monitor->volumes, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->volumes);
-  g_list_foreach (monitor->mounts, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->mounts);
-
-  g_list_foreach (monitor->disc_volumes, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->disc_volumes);
-  g_list_foreach (monitor->disc_mounts, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->disc_mounts);
-  g_list_foreach (monitor->camera_volumes, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->camera_volumes);
+  
+  list_free (monitor->last_camera_devices);
+  list_free (monitor->last_optical_disc_devices);
+  list_free (monitor->last_drive_devices);
+  list_free (monitor->last_volume_devices);
+  list_free (monitor->last_mountpoints);
+  list_free (monitor->last_mounts);
+
+  list_free (monitor->drives);
+  list_free (monitor->volumes);
+  list_free (monitor->mounts);
+
+  list_free (monitor->disc_volumes);
+  list_free (monitor->disc_mounts);
+  list_free (monitor->camera_volumes);
   
   if (G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_hal_volume_monitor_parent_class)->finalize) (object);
@@ -156,12 +181,16 @@
   
   monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
 
+  G_LOCK (hal_vm);
+  
   l = g_list_copy (monitor->mounts);
   ll = g_list_copy (monitor->disc_mounts);
   l = g_list_concat (l, ll);
 
   g_list_foreach (l, (GFunc)g_object_ref, NULL);
 
+  G_UNLOCK (hal_vm);
+
   return l;
 }
 
@@ -173,6 +202,8 @@
   
   monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
 
+  G_LOCK (hal_vm);
+
   l = g_list_copy (monitor->volumes);
   ll = g_list_copy (monitor->disc_volumes);
   l = g_list_concat (l, ll);
@@ -181,6 +212,8 @@
 
   g_list_foreach (l, (GFunc)g_object_ref, NULL);
 
+  G_UNLOCK (hal_vm);
+  
   return l;
 }
 
@@ -192,9 +225,13 @@
   
   monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
 
+  G_LOCK (hal_vm);
+
   l = g_list_copy (monitor->drives);
   g_list_foreach (l, (GFunc)g_object_ref, NULL);
 
+  G_UNLOCK (hal_vm);
+  
   return l;
 }
 
@@ -207,6 +244,8 @@
   
   monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
 
+  G_LOCK (hal_vm);
+  
   volume = NULL;
 
   for (l = monitor->volumes; l != NULL; l = l->next)
@@ -223,11 +262,17 @@
         goto found;
     }
 
+  G_UNLOCK (hal_vm);
+  
   return NULL;
 
  found:
 
-  return g_object_ref (volume);
+  g_object_ref (volume);
+  
+  G_UNLOCK (hal_vm);
+
+  return (GVolume *)volume;
 }
 
 static GMount *
@@ -239,6 +284,8 @@
   
   monitor = G_HAL_VOLUME_MONITOR (volume_monitor);
 
+  G_LOCK (hal_vm);
+  
   mount = NULL;
 
   for (l = monitor->mounts; l != NULL; l = l->next)
@@ -255,11 +302,17 @@
         goto found;
     }
 
+  G_UNLOCK (hal_vm);
+  
   return NULL;
 
  found:
 
-  return g_object_ref (mount);
+  g_object_ref (mount);
+  
+  G_UNLOCK (hal_vm);
+  
+  return (GMount *)mount;
 }
 
 static GMount *
@@ -270,9 +323,13 @@
   GHalMount *hal_mount;
   GHalVolumeMonitor *volume_monitor;
 
-  mount = NULL;
+  G_LOCK (hal_vm);
+  volume_monitor = NULL;
+  if (the_volume_monitor != NULL)
+    volume_monitor = g_object_ref (the_volume_monitor);
+  G_UNLOCK (hal_vm);
 
-  if (the_volume_monitor == NULL)
+  if (volume_monitor == NULL)
     {
       /* Dammit, no monitor is set up.. so we have to create one, find
        * what the user asks for and throw it away again. 
@@ -283,13 +340,15 @@
        */
       volume_monitor = G_HAL_VOLUME_MONITOR (g_hal_volume_monitor_new ());
     }
-  else
-    volume_monitor = g_object_ref (the_volume_monitor);
+
+  mount = NULL;
 
   /* creation of the volume monitor might actually fail */
   if (volume_monitor != NULL)
     {
       GList *l;
+
+      G_LOCK (hal_vm);
       
       for (l = volume_monitor->mounts; l != NULL; l = l->next)
         {
@@ -302,10 +361,12 @@
             }
         }
 
+      G_UNLOCK (hal_vm);
+      
       g_object_unref (volume_monitor);
     }
 
-  return mount;
+  return (GMount *)mount;
 }
 
 static void
@@ -314,7 +375,7 @@
 {
   GHalVolumeMonitor *monitor = G_HAL_VOLUME_MONITOR (user_data);
 
-  update_all (monitor);
+  update_all (monitor, TRUE);
 }
 
 static void
@@ -323,13 +384,13 @@
 {
   GHalVolumeMonitor *monitor = G_HAL_VOLUME_MONITOR (user_data);
 
-  update_all (monitor);
+  update_all (monitor, TRUE);
 }
 
 void 
 g_hal_volume_monitor_force_update (GHalVolumeMonitor *monitor)
 {
-  update_all (monitor);
+  update_all (monitor, TRUE);
 }
 
 static void
@@ -341,7 +402,7 @@
   
   /*g_warning ("hal changed");*/
   
-  update_all (monitor);
+  update_all (monitor, TRUE);
 }
 
 static GObject *
@@ -354,11 +415,14 @@
   GHalVolumeMonitorClass *klass;
   GObjectClass *parent_class;  
 
+  G_LOCK (hal_vm);
   if (the_volume_monitor != NULL)
     {
       object = g_object_ref (the_volume_monitor);
+      G_UNLOCK (hal_vm);
       return object;
     }
+  G_UNLOCK (hal_vm);
 
   /*g_warning ("creating hal vm");*/
 
@@ -392,9 +456,11 @@
                     "device_removed", G_CALLBACK (hal_changed),
                     monitor);
 		    
-  update_all (monitor);
+  update_all (monitor, FALSE);
 
+  G_LOCK (hal_vm);
   the_volume_monitor = monitor;
+  G_UNLOCK (hal_vm);
 
   return object;
 }
@@ -426,13 +492,23 @@
   GList *l;
   GFile *mount_root;
   GVolume *ret;
-
+  GHalVolumeMonitor *volume_monitor;
+  
+  /* This is called by the union volume monitor which does
+     have a ref to this. So its guaranteed to live, unfortunately
+     the pointer is not passed as an argument :/
+  */
+  ret = NULL;
+  
+  G_LOCK (hal_vm);
   if (the_volume_monitor == NULL)
-    return NULL;
+    {
+      G_UNLOCK (hal_vm);
+      return NULL;
+    }
 
-  ret = NULL;
   mount_root = g_mount_get_root (mount);
-
+  
   /* cdda:// as foreign mounts */
   for (l = the_volume_monitor->disc_volumes; l != NULL; l = l->next)
     {
@@ -460,8 +536,9 @@
     }
 
  found:
-  
   g_object_unref (mount_root);
+  
+  G_UNLOCK (hal_vm);
   return ret;
 }
 
@@ -474,6 +551,7 @@
 
   gobject_class->constructor = g_hal_volume_monitor_constructor;
   gobject_class->finalize = g_hal_volume_monitor_finalize;
+  gobject_class->dispose = g_hal_volume_monitor_dispose;
 
   monitor_class->get_mounts = get_mounts;
   monitor_class->get_volumes = get_volumes;
@@ -545,25 +623,31 @@
     }
 }
 
-GHalVolume *
-g_hal_volume_monitor_lookup_volume_for_mount_path (GHalVolumeMonitor *monitor,
+static GHalVolume *
+lookup_volume_for_mount_path (GHalVolumeMonitor *monitor,
                                                    const char         *mount_path)
 {
   GList *l;
+  GHalVolume *found;
 
+  found = NULL;
+  
   for (l = monitor->volumes; l != NULL; l = l->next)
     {
       GHalVolume *volume = l->data;
 
       if (g_hal_volume_has_mount_path (volume, mount_path))
-	return volume;
+        {
+          found = volume;
+          break;
+        }
     }
-  
-  return NULL;
+
+  return found;
 }
 
 static GHalVolume *
-g_hal_volume_monitor_lookup_volume_for_device_path (GHalVolumeMonitor *monitor,
+lookup_volume_for_device_path (GHalVolumeMonitor *monitor,
                                                     const char         *device_path)
 {
   GList *l;
@@ -776,17 +860,119 @@
 }
 
 static void
-update_all (GHalVolumeMonitor *monitor)
+list_emit (GHalVolumeMonitor *monitor,
+           const char *monitor_signal,
+           const char *object_signal,
+           GList *objects)
 {
-  update_drives (monitor);
-  update_volumes (monitor);
-  update_mounts (monitor);
-  update_discs (monitor);
-  update_cameras (monitor);
+  GList *l;
+
+  for (l = objects; l != NULL; l = l->next)
+    {
+      g_signal_emit_by_name (monitor, monitor_signal, l->data);
+      if (object_signal)
+        g_signal_emit_by_name (l->data, object_signal);
+    }
+}
+
+typedef struct {
+  GHalVolumeMonitor *monitor;
+  GList *added_drives, *removed_drives;
+  GList *added_volumes, *removed_volumes;
+  GList *added_mounts, *removed_mounts;
+} ChangedLists;
+
+
+static gboolean
+emit_lists_in_idle (gpointer data)
+{
+  ChangedLists *lists = data;
+
+  list_emit (lists->monitor,
+             "drive_disconnected", NULL,
+             lists->removed_drives);
+  list_emit (lists->monitor,
+             "drive_connected", NULL,
+             lists->added_drives);
+
+  list_emit (lists->monitor,
+             "volume_removed", "removed",
+             lists->removed_volumes);
+  list_emit (lists->monitor,
+             "volume_added", NULL,
+             lists->added_volumes);
+
+  list_emit (lists->monitor,
+             "mount_removed", "unmounted",
+             lists->removed_mounts);
+  list_emit (lists->monitor,
+             "mount_added", NULL,
+             lists->added_mounts);
+  
+  list_free (lists->removed_drives);
+  list_free (lists->added_drives);
+  list_free (lists->removed_volumes);
+  list_free (lists->added_volumes);
+  list_free (lists->removed_mounts);
+  list_free (lists->added_mounts);
+  g_object_unref (lists->monitor);
+  g_free (lists);
+  
+  return FALSE;
 }
 
+/* Must be called from idle if emit_changes, with no locks held */
 static void
-update_drives (GHalVolumeMonitor *monitor)
+update_all (GHalVolumeMonitor *monitor,
+            gboolean emit_changes)
+{
+  ChangedLists *lists;
+  GList *added_drives, *removed_drives;
+  GList *added_volumes, *removed_volumes;
+  GList *added_mounts, *removed_mounts;
+
+  added_drives = NULL;
+  removed_drives = NULL;
+  added_volumes = NULL;
+  removed_volumes = NULL;
+  added_mounts = NULL;
+  removed_mounts = NULL;
+  
+  G_LOCK (hal_vm);
+  update_drives (monitor, &added_drives, &removed_drives);
+  update_volumes (monitor, &added_volumes, &removed_volumes);
+  update_mounts (monitor, &added_mounts, &removed_mounts);
+  update_discs (monitor,
+                &added_volumes, &removed_volumes,
+                &added_mounts, &removed_mounts);
+  update_cameras (monitor, &added_volumes, &removed_volumes);
+  G_UNLOCK (hal_vm);
+
+  /* TODO: Should happen in idle */
+  if (emit_changes)
+    {
+      lists = g_new0 (ChangedLists, 1);
+      lists->monitor = g_object_ref (monitor);
+      lists->added_drives = added_drives;
+      lists->removed_drives = removed_drives;
+      
+      g_idle_add (emit_lists_in_idle, lists);
+    }
+  else
+    {
+      list_free (removed_drives);
+      list_free (added_drives);
+      list_free (removed_volumes);
+      list_free (added_volumes);
+      list_free (removed_mounts);
+      list_free (added_mounts);
+    }
+}
+
+static void
+update_drives (GHalVolumeMonitor *monitor,
+               GList **added_drives,
+               GList **removed_drives)
 {
   GList *new_drive_devices;
   GList *removed, *added;
@@ -823,8 +1009,7 @@
           /*g_warning ("hal removing drive %s", hal_device_get_property_string (d, "block.device"));*/
           g_hal_drive_disconnected (drive);
           monitor->drives = g_list_remove (monitor->drives, drive);
-          g_signal_emit_by_name (monitor, "drive_disconnected", drive);
-          g_object_unref (drive);
+          *removed_drives = g_list_prepend (*removed_drives, drive);
         }
     }
   
@@ -840,20 +1025,21 @@
           if (drive != NULL)
             {
               monitor->drives = g_list_prepend (monitor->drives, drive);
-              g_signal_emit_by_name (monitor, "drive_connected", drive);
+              *added_drives = g_list_prepend (*added_drives, g_object_ref (drive));
             }
         }
     }
   
   g_list_free (added);
   g_list_free (removed);
-  g_list_foreach (monitor->last_drive_devices, (GFunc) g_object_unref, NULL);
-  g_list_free (monitor->last_drive_devices);
+  list_free (monitor->last_drive_devices);
   monitor->last_drive_devices = new_drive_devices;
 }
 
 static void
-update_volumes (GHalVolumeMonitor *monitor)
+update_volumes (GHalVolumeMonitor *monitor,
+                GList **added_volumes,
+                GList **removed_volumes)
 {
   GList *new_volume_devices;
   GList *removed, *added;
@@ -891,9 +1077,8 @@
           /*g_warning ("hal removing vol %s", hal_device_get_property_string (d, "block.device"));*/
           g_hal_volume_removed (volume);
           monitor->volumes = g_list_remove (monitor->volumes, volume);
-          g_signal_emit_by_name (monitor, "volume_removed", volume);
-          g_signal_emit_by_name (volume, "removed");
-          g_object_unref (volume);
+
+          *removed_volumes = g_list_prepend (*removed_volumes, volume);
         }
     }
   
@@ -916,20 +1101,21 @@
           if (volume != NULL)
             {
               monitor->volumes = g_list_prepend (monitor->volumes, volume);
-              g_signal_emit_by_name (monitor, "volume_added", volume);
+              *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
             }
         }
     }
   
   g_list_free (added);
   g_list_free (removed);
-  g_list_foreach (monitor->last_volume_devices, (GFunc) g_object_unref, NULL);
-  g_list_free (monitor->last_volume_devices);
+  list_free (monitor->last_volume_devices);
   monitor->last_volume_devices = new_volume_devices;
 }
 
 static void
-update_mounts (GHalVolumeMonitor *monitor)
+update_mounts (GHalVolumeMonitor *monitor,
+               GList **added_mounts,
+               GList **removed_mounts)
 {
   GList *new_mounts;
   GList *removed, *added;
@@ -957,9 +1143,8 @@
 	{
 	  g_hal_mount_unmounted (mount);
 	  monitor->mounts = g_list_remove (monitor->mounts, mount);
-	  g_signal_emit_by_name (monitor, "mount_removed", mount);
-	  g_signal_emit_by_name (mount, "unmounted");
-	  g_object_unref (mount);
+
+          *removed_mounts = g_list_prepend (*removed_mounts, mount);
 	}
     }
   
@@ -969,16 +1154,16 @@
 
       device_path = g_unix_mount_get_device_path (mount_entry);
       mount_path = g_unix_mount_get_mount_path (mount_entry);
-      volume = g_hal_volume_monitor_lookup_volume_for_device_path (monitor, device_path);
+      volume = lookup_volume_for_device_path (monitor, device_path);
       if (volume == NULL)
-        volume = g_hal_volume_monitor_lookup_volume_for_mount_path (monitor, mount_path);
+        volume = lookup_volume_for_mount_path (monitor, mount_path);
 
       /*g_warning ("hal adding mount %s (vol %p)", g_unix_mount_get_device_path (mount_entry), volume);*/
       mount = g_hal_mount_new (G_VOLUME_MONITOR (monitor), mount_entry, monitor->pool, volume);
       if (mount)
 	{
 	  monitor->mounts = g_list_prepend (monitor->mounts, mount);
-	  g_signal_emit_by_name (monitor, "mount_added", mount);
+          *added_mounts = g_list_prepend (*added_mounts, g_object_ref (mount));
 	}
     }
   
@@ -991,7 +1176,11 @@
 }
 
 static void
-update_discs (GHalVolumeMonitor *monitor)
+update_discs (GHalVolumeMonitor *monitor,
+              GList **added_volumes,
+              GList **removed_volumes,
+              GList **added_mounts,
+              GList **removed_mounts)
 {
   GList *new_optical_disc_devices;
   GList *removed, *added;
@@ -1041,9 +1230,7 @@
         {
 	  g_hal_mount_unmounted (mount);
 	  monitor->disc_mounts = g_list_remove (monitor->disc_mounts, mount);
-	  g_signal_emit_by_name (monitor, "mount_removed", mount);
-	  g_signal_emit_by_name (mount, "unmounted");
-	  g_object_unref (mount);
+          *removed_mounts = g_list_prepend (*removed_mounts, mount);
         }
 
       volume = find_disc_volume_by_udi (monitor, udi);
@@ -1051,9 +1238,7 @@
         {
 	  g_hal_volume_removed (volume);
 	  monitor->disc_volumes = g_list_remove (monitor->disc_volumes, volume);
-	  g_signal_emit_by_name (monitor, "volume_removed", volume);
-	  g_signal_emit_by_name (volume, "removed");
-	  g_object_unref (volume);
+          *removed_volumes = g_list_prepend (*removed_volumes, volume);
         }
     }
   
@@ -1117,12 +1302,12 @@
           if (volume != NULL)
             {
               monitor->disc_volumes = g_list_prepend (monitor->disc_volumes, volume);
-              g_signal_emit_by_name (monitor, "volume_added", volume);
+              *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
               
               if (mount != NULL)
                 {
                   monitor->disc_mounts = g_list_prepend (monitor->disc_mounts, mount);
-                  g_signal_emit_by_name (monitor, "mount_added", mount);
+                  *added_mounts = g_list_prepend (*added_mounts, g_object_ref (mount));
                 }
             }
         }
@@ -1130,13 +1315,14 @@
 
   g_list_free (added);
   g_list_free (removed);
-  g_list_foreach (monitor->last_optical_disc_devices, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->last_optical_disc_devices);
+  list_free (monitor->last_optical_disc_devices);
   monitor->last_optical_disc_devices = new_optical_disc_devices;
 }
 
 static void
-update_cameras (GHalVolumeMonitor *monitor)
+update_cameras (GHalVolumeMonitor *monitor,
+                GList **added_volumes,
+                GList **removed_volumes)
 {
 #ifdef HAVE_GPHOTO2
   GList *new_camera_devices;
@@ -1192,9 +1378,7 @@
         {
 	  g_hal_volume_removed (volume);
 	  monitor->camera_volumes = g_list_remove (monitor->camera_volumes, volume);
-	  g_signal_emit_by_name (monitor, "volume_removed", volume);
-	  g_signal_emit_by_name (volume, "removed");
-	  g_object_unref (volume);
+          *removed_volumes = g_list_prepend (*removed_volumes, volume);
         }
     }
   
@@ -1227,14 +1411,13 @@
       if (volume != NULL)
         {
           monitor->camera_volumes = g_list_prepend (monitor->camera_volumes, volume);
-          g_signal_emit_by_name (monitor, "volume_added", volume);
+          *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
         }
     }
 
   g_list_free (added);
   g_list_free (removed);
-  g_list_foreach (monitor->last_camera_devices, (GFunc)g_object_unref, NULL);
-  g_list_free (monitor->last_camera_devices);
+  list_free (monitor->last_camera_devices);
   monitor->last_camera_devices = new_camera_devices;
 #endif
 }

Modified: trunk/hal/ghalvolumemonitor.h
==============================================================================
--- trunk/hal/ghalvolumemonitor.h	(original)
+++ trunk/hal/ghalvolumemonitor.h	Tue Mar  4 11:20:26 2008
@@ -53,9 +53,6 @@
 GType g_hal_volume_monitor_get_type (void) G_GNUC_CONST;
 
 GVolumeMonitor *g_hal_volume_monitor_new                          (void);
-GHalVolume     *g_hal_volume_monitor_lookup_volume_for_mount_path (GHalVolumeMonitor *monitor,
-                                                                   const char        *mount_path);
-
 void            g_hal_volume_monitor_force_update                 (GHalVolumeMonitor *monitor);
 
 void            g_hal_volume_monitor_register                     (GIOModule         *module);



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