gio/gunixmounts.c: Don't use mtime to monitor mounts on /proc/

Fix get_mounts_timestamp() to not use a stat'ed mtime for /proc/ files.
Instead, use mount_poller_time if /proc/ watch is running, or otherwise
return a new generated timestamp to always assume mounts-changed, which
is safer than previous behaviour of always assuming mounts-not-changed
(as mtime never changes for /proc/ files when queried from the same
process).

We say it's safer because allows caches depending on:

g_unix_mounts_get(&time_read)
g_unix_mounts_changed_since()

to drop possibly outdated/duplicated values, as that was the case for the
GIO mounts cache used in gio/glocalfile.c which provides mount info for
g_file_query_filesystem_info() call, as described in below referenced bug.

This fix complements related commit bd9e266e11

https://bugzilla.gnome.org/show_bug.cgi?id=787731
This commit is contained in:
Nelson Benítez León 2017-09-08 21:42:14 +05:00
parent 32a9b88b20
commit c1a31c3aaa

View File

@ -148,6 +148,7 @@ G_DEFINE_BOXED_TYPE (GUnixMountPoint, g_unix_mount_point,
static GList *_g_get_unix_mounts (void); static GList *_g_get_unix_mounts (void);
static GList *_g_get_unix_mount_points (void); static GList *_g_get_unix_mount_points (void);
static gboolean proc_mounts_watch_is_running (void);
static guint64 mount_poller_time = 0; static guint64 mount_poller_time = 0;
@ -1368,14 +1369,25 @@ get_mounts_timestamp (void)
struct stat buf; struct stat buf;
monitor_file = get_mtab_monitor_file (); monitor_file = get_mtab_monitor_file ();
if (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) if (stat (monitor_file, &buf) == 0)
return (guint64)buf.st_mtime; return (guint64)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;
}
else else
{ {
return mount_poller_time; /* Case of /proc/ file not being monitored - Be on the safe side and
* send a new timestamp to force g_unix_mounts_changed_since() to
* 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 ();
} }
return 0; return 0;
} }
@ -1566,6 +1578,13 @@ static GFileMonitor *mtab_monitor;
static GSource *proc_mounts_watch_source; static GSource *proc_mounts_watch_source;
static GList *mount_poller_mounts; static GList *mount_poller_mounts;
static gboolean
proc_mounts_watch_is_running (void)
{
return proc_mounts_watch_source != NULL &&
!g_source_is_destroyed (proc_mounts_watch_source);
}
static void static void
fstab_file_changed (GFileMonitor *monitor, fstab_file_changed (GFileMonitor *monitor,
GFile *file, GFile *file,
@ -1602,7 +1621,10 @@ proc_mounts_changed (GIOChannel *channel,
gpointer user_data) gpointer user_data)
{ {
if (cond & G_IO_ERR) if (cond & G_IO_ERR)
g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED]); {
mount_poller_time = (guint64) g_get_monotonic_time ();
g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED]);
}
return TRUE; return TRUE;
} }
@ -1652,7 +1674,10 @@ mount_monitor_stop (void)
} }
if (proc_mounts_watch_source != NULL) if (proc_mounts_watch_source != NULL)
g_source_destroy (proc_mounts_watch_source); {
g_source_destroy (proc_mounts_watch_source);
proc_mounts_watch_source = NULL;
}
if (mtab_monitor) if (mtab_monitor)
{ {