diff options
author | Alexander Larsson <alexl@redhat.com> | 2008-03-04 11:20:26 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2008-03-04 11:20:26 +0000 |
commit | 30570f318b2fac6553f5a32350c2886bbdac708b (patch) | |
tree | 9ad52a2270354c8345807a35d951d6f0f246d86e | |
parent | c71bb3706203039a18dac2eb3dc2ee53c8493cb8 (diff) | |
download | gvfs-30570f318b2fac6553f5a32350c2886bbdac708b.tar.gz |
Properly lock around volume monitors and volume monitor objects. Emit all
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.
svn path=/trunk/; revision=1522
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | client/gdaemonmount.c | 85 | ||||
-rw-r--r-- | client/gdaemonvolumemonitor.c | 55 | ||||
-rw-r--r-- | hal/ghaldrive.c | 242 | ||||
-rw-r--r-- | hal/ghalmount.c | 218 | ||||
-rw-r--r-- | hal/ghalvolume.c | 321 | ||||
-rw-r--r-- | hal/ghalvolumemonitor.c | 385 | ||||
-rw-r--r-- | hal/ghalvolumemonitor.h | 3 |
8 files changed, 919 insertions, 403 deletions
@@ -1,5 +1,18 @@ 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. + +2008-03-04 Alexander Larsson <alexl@redhat.com> + * common/gmountsource.c: * common/gmounttracker.c: Work around problems with type registering when the common code diff --git a/client/gdaemonmount.c b/client/gdaemonmount.c index 4d13bdd0..fd66e645 100644 --- a/client/gdaemonmount.c +++ b/client/gdaemonmount.c @@ -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 @@ static GDrive * 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 @@ static gboolean 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 @@ g_daemon_mount_set_foreign_volume (GDaemonMount *mount, 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 @@ g_daemon_mount_eject (GMount *mount, 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 @@ g_daemon_mount_eject_finish (GMount *mount, { 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 diff --git a/client/gdaemonvolumemonitor.c b/client/gdaemonvolumemonitor.c index c1f79d3b..61f3a2c0 100644 --- a/client/gdaemonvolumemonitor.c +++ b/client/gdaemonvolumemonitor.c @@ -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 @@ get_mounts (GVolumeMonitor *volume_monitor) 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 @@ get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) return NULL; } - static GMount * get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) { @@ -118,20 +117,18 @@ g_daemon_volume_monitor_find_mount_by_mount_info (GMountInfo *mount_info) { 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 @@ mount_added (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info) 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 @@ mount_added (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info) g_object_ref (mount); } - G_UNLOCK (_the_daemon_volume_monitor); + G_UNLOCK (daemon_vm); if (mount) { @@ -180,7 +177,7 @@ mount_removed (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info) { 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 @@ mount_removed (GDaemonVolumeMonitor *daemon_monitor, GMountInfo *mount_info) 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 @@ g_daemon_volume_monitor_finalize (GObject *object) { 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 @@ g_daemon_volume_monitor_finalize (GObject *object) 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 @@ g_daemon_volume_monitor_class_init (GDaemonVolumeMonitorClass *klass) 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; diff --git a/hal/ghaldrive.c b/hal/ghaldrive.c index f2259c2b..3159d40a 100644 --- a/hal/ghaldrive.c +++ b/hal/ghaldrive.c @@ -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 @@ _drive_get_icon (HalDevice *d) 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 @@ _do_update_from_hal (GHalDrive *d) } } +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 @@ _update_from_hal (GHalDrive *d, gboolean emit_changed) 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 @@ _update_from_hal (GHalDrive *d, gboolean emit_changed) 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 @@ g_hal_drive_new (GVolumeMonitor *volume_monitor, 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 @@ g_hal_drive_get_volumes (GDrive *drive) 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 @@ static gboolean 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 @@ g_hal_drive_eject_do (GDrive *drive, 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 @@ g_hal_drive_eject_do (GDrive *drive, 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 @@ g_hal_drive_eject (GDrive *drive, 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 @@ g_hal_drive_eject (GDrive *drive, 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 @@ g_hal_drive_poll_for_media (GDrive *drive, 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_hal_drive_poll_for_media (GDrive *drive, 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 @@ g_hal_drive_get_identifier (GDrive *drive, 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 @@ g_hal_drive_enumerate_identifiers (GDrive *drive) 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_hal_drive_enumerate_identifiers (GDrive *drive) g_strdup (G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE)); + G_UNLOCK (hal_drive); + /* Null-terminate */ g_ptr_array_add (res, NULL); diff --git a/hal/ghalmount.c b/hal/ghalmount.c index a3e700de..06a32172 100644 --- a/hal/ghalmount.c +++ b/hal/ghalmount.c @@ -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 @@ g_hal_mount_init (GHalMount *hal_mount) { } +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 @@ do_update_from_hal (GHalMount *m) 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 @@ do_update_from_hal (GHalMount *m) 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 @@ update_from_hal (GHalMount *m, gboolean emit_changed) 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 @@ update_from_hal (GHalMount *m, gboolean emit_changed) 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 @@ g_hal_mount_new_for_hal_device (GVolumeMonitor *volume_monitor, 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 @@ g_hal_mount_override_name (GHalMount *mount, const char *name) 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 @@ g_hal_mount_override_icon (GHalMount *mount, GIcon *icon) else mount->override_icon = NULL; + G_UNLOCK (hal_mount); + update_from_hal (mount, TRUE); } @@ -743,121 +751,171 @@ g_hal_mount_new (GVolumeMonitor *volume_monitor, 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 @@ g_hal_mount_can_eject (GMount *mount) 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 @@ g_hal_mount_unmount (GMount *mount, 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 @@ g_hal_mount_eject (GMount *mount, 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 @@ g_hal_mount_eject_finish (GMount *mount, { 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 diff --git a/hal/ghalvolume.c b/hal/ghalvolume.c index 0df09816..27e282e8 100644 --- a/hal/ghalvolume.c +++ b/hal/ghalvolume.c @@ -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 @@ g_hal_volume_init (GHalVolume *hal_volume) { } +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 @@ do_update_from_hal (GHalVolume *mv) 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 @@ do_update_from_hal_for_camera (GHalVolume *v) 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 @@ do_update_from_hal_for_camera (GHalVolume *v) 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 @@ do_update_from_hal_for_camera (GHalVolume *v) 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 @@ update_from_hal (GHalVolume *mv, gboolean emit_changed) 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 @@ update_from_hal (GHalVolume *mv, gboolean emit_changed) 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_new (GVolumeMonitor *volume_monitor, } /** - * 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_volume_removed (GHalVolume *volume) 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 @@ g_hal_volume_has_udi (GHalVolume *volume, 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 @@ g_hal_volume_has_uuid (GHalVolume *volume, 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 @@ g_hal_volume_adopt_foreign_mount (GHalVolume *volume, GMount *foreign_mount) 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 @@ g_hal_volume_has_foreign_mount_root (GHalVolume *volume, 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 @@ g_hal_volume_mount (GVolume *volume, 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 @@ g_hal_volume_mount (GVolume *volume, argv[4] = "-n"; spawn_do (volume, cancellable, callback, user_data, argv); } + G_UNLOCK (hal_volume); } static gboolean @@ -968,11 +1048,17 @@ g_hal_volume_mount_finish (GVolume *volume, 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 @@ g_hal_volume_eject (GVolume *volume, 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 @@ g_hal_volume_eject_finish (GVolume *volume, 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 @@ g_hal_volume_get_identifier (GVolume *volume, 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 @@ g_hal_volume_enumerate_identifiers (GVolume *volume) GPtrArray *res; const char *label, *uuid; + G_LOCK (hal_volume); + res = g_ptr_array_new (); g_ptr_array_add (res, @@ -1075,6 +1176,8 @@ g_hal_volume_enumerate_identifiers (GVolume *volume) /* Null-terminate */ g_ptr_array_add (res, NULL); + + G_UNLOCK (hal_volume); return (char **)g_ptr_array_free (res, FALSE); } diff --git a/hal/ghalvolumemonitor.c b/hal/ghalvolumemonitor.c index d0e99f5b..0ab8570b 100644 --- a/hal/ghalvolumemonitor.c +++ b/hal/ghalvolumemonitor.c @@ -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 mounts_changed (GUnixMountMonitor *mount_monitor, 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 @@ get_hal_pool (void) } 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_hal_volume_monitor_finalize (GObject *object) 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 @@ get_mounts (GVolumeMonitor *volume_monitor) 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 @@ get_volumes (GVolumeMonitor *volume_monitor) 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 @@ get_volumes (GVolumeMonitor *volume_monitor) g_list_foreach (l, (GFunc)g_object_ref, NULL); + G_UNLOCK (hal_vm); + return l; } @@ -192,9 +225,13 @@ get_connected_drives (GVolumeMonitor *volume_monitor) 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 @@ get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) 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 @@ get_volume_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) 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 @@ get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) 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 @@ get_mount_for_uuid (GVolumeMonitor *volume_monitor, const char *uuid) 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 @@ get_mount_for_mount_path (const char *mount_path, 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 @@ get_mount_for_mount_path (const char *mount_path, */ 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 @@ get_mount_for_mount_path (const char *mount_path, } } + G_UNLOCK (hal_vm); + g_object_unref (volume_monitor); } - return mount; + return (GMount *)mount; } static void @@ -314,7 +375,7 @@ mountpoints_changed (GUnixMountMonitor *mount_monitor, { GHalVolumeMonitor *monitor = G_HAL_VOLUME_MONITOR (user_data); - update_all (monitor); + update_all (monitor, TRUE); } static void @@ -323,13 +384,13 @@ mounts_changed (GUnixMountMonitor *mount_monitor, { 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 @@ hal_changed (HalPool *pool, /*g_warning ("hal changed");*/ - update_all (monitor); + update_all (monitor, TRUE); } static GObject * @@ -354,11 +415,14 @@ g_hal_volume_monitor_constructor (GType type, 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 @@ g_hal_volume_monitor_constructor (GType type, "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 @@ adopt_orphan_mount (GMount *mount) 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 @@ adopt_orphan_mount (GMount *mount) } found: - g_object_unref (mount_root); + + G_UNLOCK (hal_vm); return ret; } @@ -474,6 +551,7 @@ g_hal_volume_monitor_class_init (GHalVolumeMonitorClass *klass) 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 @@ diff_sorted_lists (GList *list1, } } -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 @@ should_drive_be_ignored (HalPool *pool, HalDevice *d) } static void -update_all (GHalVolumeMonitor *monitor) +list_emit (GHalVolumeMonitor *monitor, + const char *monitor_signal, + const char *object_signal, + GList *objects) +{ + 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_all (GHalVolumeMonitor *monitor, + gboolean emit_changes) { - update_drives (monitor); - update_volumes (monitor); - update_mounts (monitor); - update_discs (monitor); - update_cameras (monitor); + 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) +update_drives (GHalVolumeMonitor *monitor, + GList **added_drives, + GList **removed_drives) { GList *new_drive_devices; GList *removed, *added; @@ -823,8 +1009,7 @@ update_drives (GHalVolumeMonitor *monitor) /*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 @@ update_drives (GHalVolumeMonitor *monitor) 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 @@ update_volumes (GHalVolumeMonitor *monitor) /*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 @@ update_volumes (GHalVolumeMonitor *monitor) 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 @@ update_mounts (GHalVolumeMonitor *monitor) { 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 @@ update_mounts (GHalVolumeMonitor *monitor) 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 @@ update_mounts (GHalVolumeMonitor *monitor) } 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 @@ update_discs (GHalVolumeMonitor *monitor) { 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 @@ update_discs (GHalVolumeMonitor *monitor) { 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 @@ update_discs (GHalVolumeMonitor *monitor) 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 @@ update_discs (GHalVolumeMonitor *monitor) 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 @@ update_cameras (GHalVolumeMonitor *monitor) { 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 @@ update_cameras (GHalVolumeMonitor *monitor) 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 } diff --git a/hal/ghalvolumemonitor.h b/hal/ghalvolumemonitor.h index 8a198b78..d12dda1f 100644 --- a/hal/ghalvolumemonitor.h +++ b/hal/ghalvolumemonitor.h @@ -53,9 +53,6 @@ struct _GHalVolumeMonitorClass { 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); |