[glib/wip/oholy/gunixmountmonitor-thread-safe] gunixmounts: Make GUnixMountMonitor thread-safe
- From: Ondrej Holy <oholy src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/oholy/gunixmountmonitor-thread-safe] gunixmounts: Make GUnixMountMonitor thread-safe
- Date: Mon, 10 Feb 2020 15:31:26 +0000 (UTC)
commit 79cb4c61f4fe5a3353f7cd8e4fb502c12e51de2e
Author: Ondrej Holy <oholy redhat com>
Date: Mon Feb 10 16:00:42 2020 +0100
gunixmounts: Make GUnixMountMonitor thread-safe
The Nautilus test suite often crashes with "GLib-FATAL-CRITICAL:
g_source_is_destroyed: assertion 'g_atomic_int_get (&source->ref_count)
> 0' failed" if it is started with "GIO_USE_VOLUME_MONITOR=unix". This
is because GUnixMountMonitor is simultaneously used from multiple
threads over GLocalFile and GVolumeMonitor APIs. Let's add guards for
proc_mounts_watch_source and mount_poller_time variables to prevent
those crashes.
Fixes: https://gitlab.gnome.org/GNOME/glib/issues/2030
gio/gunixmounts.c | 34 ++++++++++++++++++++++++++++++----
1 file changed, 30 insertions(+), 4 deletions(-)
---
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
index cbf2ee99e..513c4616b 100644
--- a/gio/gunixmounts.c
+++ b/gio/gunixmounts.c
@@ -148,6 +148,8 @@ struct _GUnixMountPoint {
G_DEFINE_BOXED_TYPE (GUnixMountPoint, g_unix_mount_point,
g_unix_mount_point_copy, g_unix_mount_point_free)
+G_LOCK_DEFINE_STATIC (proc_mounts_source);
+
static GList *_g_get_unix_mounts (void);
static GList *_g_get_unix_mount_points (void);
static gboolean proc_mounts_watch_is_running (void);
@@ -1485,18 +1487,21 @@ get_mounts_timestamp (void)
{
const char *monitor_file;
struct stat buf;
+ gint64 timestamp = 0;
+
+ G_LOCK (proc_mounts_source);
monitor_file = get_mtab_monitor_file ();
/* Don't return mtime for /proc/ files */
if (monitor_file && !g_str_has_prefix (monitor_file, "/proc/"))
{
if (stat (monitor_file, &buf) == 0)
- return (guint64)buf.st_mtime;
+ timestamp = buf.st_mtime;
}
else if (proc_mounts_watch_is_running ())
{
/* it's being monitored by poll, so return mount_poller_time */
- return mount_poller_time;
+ timestamp = mount_poller_time;
}
else
{
@@ -1505,9 +1510,12 @@ get_mounts_timestamp (void)
* return TRUE so any application caches depending on it (like eg.
* the one in GIO) get invalidated and don't hold possibly outdated
* data - see Bug 787731 */
- return (guint64) g_get_monotonic_time ();
+ timestamp = g_get_monotonic_time ();
}
- return 0;
+
+ G_UNLOCK (proc_mounts_source);
+
+ return timestamp;
}
static guint64
@@ -1708,6 +1716,7 @@ static GSource *proc_mounts_watch_source;
static GList *mount_poller_mounts;
static guint mtab_file_changed_id;
+/* Called with proc_mounts_source lock held. */
static gboolean
proc_mounts_watch_is_running (void)
{
@@ -1768,7 +1777,10 @@ proc_mounts_changed (GIOChannel *channel,
{
if (cond & G_IO_ERR)
{
+ G_LOCK (proc_mounts_source);
mount_poller_time = (guint64) g_get_monotonic_time ();
+ G_UNLOCK (proc_mounts_source);
+
g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED]);
}
@@ -1802,7 +1814,10 @@ mount_change_poller (gpointer user_data)
if (has_changed)
{
+ G_LOCK (proc_mounts_source);
mount_poller_time = (guint64) g_get_monotonic_time ();
+ G_UNLOCK (proc_mounts_source);
+
g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTPOINTS_CHANGED]);
}
@@ -1819,11 +1834,13 @@ mount_monitor_stop (void)
g_object_unref (fstab_monitor);
}
+ G_LOCK (proc_mounts_source);
if (proc_mounts_watch_source != NULL)
{
g_source_destroy (proc_mounts_watch_source);
proc_mounts_watch_source = NULL;
}
+ G_UNLOCK (proc_mounts_source);
if (mtab_monitor)
{
@@ -1869,7 +1886,10 @@ mount_monitor_start (void)
}
else
{
+ G_LOCK (proc_mounts_source);
+
proc_mounts_watch_source = g_io_create_watch (proc_mounts_channel, G_IO_ERR);
+ mount_poller_time = (guint64) g_get_monotonic_time ();
g_source_set_callback (proc_mounts_watch_source,
(GSourceFunc) proc_mounts_changed,
NULL, NULL);
@@ -1877,6 +1897,8 @@ mount_monitor_start (void)
g_main_context_get_thread_default ());
g_source_unref (proc_mounts_watch_source);
g_io_channel_unref (proc_mounts_channel);
+
+ G_UNLOCK (proc_mounts_source);
}
}
else
@@ -1889,6 +1911,8 @@ mount_monitor_start (void)
}
else
{
+ G_LOCK (proc_mounts_source);
+
proc_mounts_watch_source = g_timeout_source_new_seconds (3);
mount_poller_mounts = _g_get_unix_mounts ();
mount_poller_time = (guint64)g_get_monotonic_time ();
@@ -1898,6 +1922,8 @@ mount_monitor_start (void)
g_source_attach (proc_mounts_watch_source,
g_main_context_get_thread_default ());
g_source_unref (proc_mounts_watch_source);
+
+ G_UNLOCK (proc_mounts_source);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]