summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2008-03-04 11:20:26 +0000
committerAlexander Larsson <alexl@src.gnome.org>2008-03-04 11:20:26 +0000
commit30570f318b2fac6553f5a32350c2886bbdac708b (patch)
tree9ad52a2270354c8345807a35d951d6f0f246d86e
parentc71bb3706203039a18dac2eb3dc2ee53c8493cb8 (diff)
downloadgvfs-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--ChangeLog13
-rw-r--r--client/gdaemonmount.c85
-rw-r--r--client/gdaemonvolumemonitor.c55
-rw-r--r--hal/ghaldrive.c242
-rw-r--r--hal/ghalmount.c218
-rw-r--r--hal/ghalvolume.c321
-rw-r--r--hal/ghalvolumemonitor.c385
-rw-r--r--hal/ghalvolumemonitor.h3
8 files changed, 919 insertions, 403 deletions
diff --git a/ChangeLog b/ChangeLog
index d672c3d3..05eb2a3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);