diff --git a/glib/gutils.c b/glib/gutils.c index 186ef7d07..d73b6474b 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -598,6 +598,7 @@ static gchar *g_user_state_dir = NULL; static gchar *g_user_runtime_dir = NULL; static gchar **g_system_config_dirs = NULL; static gchar **g_user_special_dirs = NULL; +static gchar *g_tmp_dir = NULL; /* fifteen minutes of fame for everybody */ #define G_USER_DIRS_EXPIRE 15 * 60 @@ -941,6 +942,17 @@ g_get_home_dir (void) return home_dir; } +void +_g_unset_cached_tmp_dir (void) +{ + G_LOCK (g_utils_global); + /* We have to leak the old value, as user code could be retaining pointers + * to it. */ + g_ignore_leak (g_tmp_dir); + g_tmp_dir = NULL; + G_UNLOCK (g_utils_global); +} + /** * g_get_tmp_dir: * @@ -964,22 +976,33 @@ g_get_home_dir (void) const gchar * g_get_tmp_dir (void) { - static gchar *tmp_dir; + G_LOCK (g_utils_global); - if (g_once_init_enter (&tmp_dir)) + if (g_tmp_dir == NULL) { gchar *tmp; -#ifdef G_OS_WIN32 - tmp = g_strdup (g_getenv ("TEMP")); + tmp = g_strdup (g_getenv ("G_TEST_TMPDIR")); + if (tmp == NULL || *tmp == '\0') + { + g_free (tmp); + tmp = g_strdup (g_getenv ( +#ifdef G_OS_WIN32 + "TEMP" +#else /* G_OS_WIN32 */ + "TMPDIR" +#endif /* G_OS_WIN32 */ + )); + } + +#ifdef G_OS_WIN32 if (tmp == NULL || *tmp == '\0') { g_free (tmp); tmp = get_windows_directory_root (); } #else /* G_OS_WIN32 */ - tmp = g_strdup (g_getenv ("TMPDIR")); #ifdef P_tmpdir if (tmp == NULL || *tmp == '\0') @@ -1000,10 +1023,12 @@ g_get_tmp_dir (void) } #endif /* !G_OS_WIN32 */ - g_once_init_leave (&tmp_dir, tmp); + g_tmp_dir = g_steal_pointer (&tmp); } - return tmp_dir; + G_UNLOCK (g_utils_global); + + return g_tmp_dir; } /** diff --git a/glib/gutilsprivate.h b/glib/gutilsprivate.h index f7d435d61..0d9b0df14 100644 --- a/glib/gutilsprivate.h +++ b/glib/gutilsprivate.h @@ -59,6 +59,8 @@ g_nearest_pow (gsize num) return n + 1; } +void _g_unset_cached_tmp_dir (void); + G_END_DECLS #endif /* __G_UTILS_PRIVATE_H__ */ diff --git a/tools/glib.supp b/tools/glib.supp index 0609db44e..5b03557d9 100644 --- a/tools/glib.supp +++ b/tools/glib.supp @@ -840,6 +840,19 @@ fun:g_set_user_dirs } +# _g_unset_cached_tmp_dir() deliberately leaks the previous cached g_get_tmp_dir() values. +# These will not all be reachable on exit. +{ + g_get_tmp_dir + Memcheck:Leak + match-leak-kinds:definite,reachable + fun:malloc + ... + fun:g_get_tmp_dir + ... + fun:g_test_init +} + # g_get_system_data_dirs() caches a one-time allocation { g_get_system_data_dirs