diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c index cbf2ee99e..b716f22e4 100644 --- a/gio/gunixmounts.c +++ b/gio/gunixmounts.c @@ -152,7 +152,11 @@ static GList *_g_get_unix_mounts (void); static GList *_g_get_unix_mount_points (void); static gboolean proc_mounts_watch_is_running (void); +G_LOCK_DEFINE_STATIC (proc_mounts_source); + +/* Protected by proc_mounts_source lock */ static guint64 mount_poller_time = 0; +static GSource *proc_mounts_watch_source; #ifdef HAVE_SYS_MNTTAB_H #define MNTOPT_RO "ro" @@ -1485,18 +1489,21 @@ get_mounts_timestamp (void) { const char *monitor_file; struct stat buf; + guint64 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 +1512,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 @@ -1704,10 +1714,10 @@ G_DEFINE_TYPE (GUnixMountMonitor, g_unix_mount_monitor, G_TYPE_OBJECT) static GContextSpecificGroup mount_monitor_group; static GFileMonitor *fstab_monitor; static GFileMonitor *mtab_monitor; -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 +1778,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 +1815,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 +1835,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,6 +1887,8 @@ mount_monitor_start (void) } else { + G_LOCK (proc_mounts_source); + proc_mounts_watch_source = g_io_create_watch (proc_mounts_channel, G_IO_ERR); g_source_set_callback (proc_mounts_watch_source, (GSourceFunc) proc_mounts_changed, @@ -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); } }