[libgsystem] fileutil: Add lock around pathname caching
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgsystem] fileutil: Add lock around pathname caching
- Date: Fri, 6 Sep 2013 22:22:41 +0000 (UTC)
commit 2d24676846e3058d7a03bc127591f9fdcc346fab
Author: Colin Walters <walters verbum org>
Date: Fri Sep 6 17:17:24 2013 -0400
fileutil: Add lock around pathname caching
If two threads both call gs_file_get_path_cached() on the same GFile,
then it's possible that both threads see the pathname isn't cached,
and set the qdata. The second one will end up freeing the cached
qdata from the first, causing it to read freed memory.
Fix this by just slapping a lock around the whole business.
This was observed in the real world in ostree where two threads were
calling gs_file_get_path_cached() on the shared repo->tmp_dir.
But really, what we want to do is two things:
1) Upstream this into gio
2) Stop using gs_file_get_path_cached() so much; instead, we
should be using openat() and friends. This will also
avoid malloc, and help us earn our UNIX merit badge.
gsystem-file-utils.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
---
diff --git a/gsystem-file-utils.c b/gsystem-file-utils.c
index f70239c..6291027 100644
--- a/gsystem-file-utils.c
+++ b/gsystem-file-utils.c
@@ -743,6 +743,8 @@ gs_file_linkcopy_sync_data (GFile *src,
return linkcopy_internal (src, dest, flags, TRUE, cancellable, error);
}
+G_LOCK_DEFINE_STATIC (pathname_cache);
+
/**
* gs_file_get_path_cached:
*
@@ -758,6 +760,8 @@ gs_file_get_path_cached (GFile *file)
if (G_UNLIKELY (_file_path_quark) == 0)
_file_path_quark = g_quark_from_static_string ("gsystem-file-path");
+ G_LOCK (pathname_cache);
+
path = g_object_get_qdata ((GObject*)file, _file_path_quark);
if (!path)
{
@@ -765,6 +769,9 @@ gs_file_get_path_cached (GFile *file)
g_assert (path != NULL);
g_object_set_qdata_full ((GObject*)file, _file_path_quark, (char*)path, (GDestroyNotify)g_free);
}
+
+ G_UNLOCK (pathname_cache);
+
return path;
}
@@ -783,12 +790,17 @@ gs_file_get_basename_cached (GFile *file)
if (G_UNLIKELY (_file_name_quark) == 0)
_file_name_quark = g_quark_from_static_string ("gsystem-file-name");
+ G_LOCK (pathname_cache);
+
name = g_object_get_qdata ((GObject*)file, _file_name_quark);
if (!name)
{
name = g_file_get_basename (file);
g_object_set_qdata_full ((GObject*)file, _file_name_quark, (char*)name, (GDestroyNotify)g_free);
}
+
+ G_UNLOCK (pathname_cache);
+
return name;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]