summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <pwithnall@endlessos.org>2020-09-30 16:16:11 +0100
committerChristian Hergert <chergert@redhat.com>2020-12-17 10:30:54 -0800
commite4af46fc09b99c606a5c2a0af511e0352ff1b4be (patch)
tree075b40ed277b02034bfc385588ac6f5e16c359c6
parentbacbec652d356895ec493f3de2f2f6f4c7dafde0 (diff)
downloadglib-wip/chergert/merge-private-fix.tar.gz
gthread: Destroy value after replacing it in g_private_replace()wip/chergert/merge-private-fix
If the old value is destroyed before updating the TLS value in pthreads (or the Windows equivalent) then there’s a risk of infinite recursion if `g_private_replace()` is called from within the `GDestroyNotify`. Avoid that by destroying the old value after doing the TLS update. Thanks to Matthias Clasen for diagnosing the issue. Signed-off-by: Philip Withnall <pwithnall@endlessos.org> Fixes: #2210
-rw-r--r--glib/gthread-posix.c5
-rw-r--r--glib/gthread-win32.c2
2 files changed, 4 insertions, 3 deletions
diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c
index f36055925..f09f58a15 100644
--- a/glib/gthread-posix.c
+++ b/glib/gthread-posix.c
@@ -1116,11 +1116,12 @@ g_private_replace (GPrivate *key,
gint status;
old = pthread_getspecific (*impl);
- if (old && key->notify)
- key->notify (old);
if G_UNLIKELY ((status = pthread_setspecific (*impl, value)) != 0)
g_thread_abort (status, "pthread_setspecific");
+
+ if (old && key->notify)
+ key->notify (old);
}
/* {{{1 GThread */
diff --git a/glib/gthread-win32.c b/glib/gthread-win32.c
index 54f74f2f8..0c37dc6c1 100644
--- a/glib/gthread-win32.c
+++ b/glib/gthread-win32.c
@@ -373,9 +373,9 @@ g_private_replace (GPrivate *key,
gpointer old;
old = TlsGetValue (impl);
+ TlsSetValue (impl, value);
if (old && key->notify)
key->notify (old);
- TlsSetValue (impl, value);
}
/* {{{1 GThread */