gthread: Destroy value after replacing it in g_private_replace()

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
This commit is contained in:
Philip Withnall 2020-09-30 16:16:11 +01:00
parent 2d788652fd
commit 8c76bec779
2 changed files with 4 additions and 3 deletions

View File

@ -1116,11 +1116,12 @@ g_private_replace (GPrivate *key,
gint status; gint status;
old = pthread_getspecific (*impl); old = pthread_getspecific (*impl);
if (old && key->notify)
key->notify (old);
if G_UNLIKELY ((status = pthread_setspecific (*impl, value)) != 0) if G_UNLIKELY ((status = pthread_setspecific (*impl, value)) != 0)
g_thread_abort (status, "pthread_setspecific"); g_thread_abort (status, "pthread_setspecific");
if (old && key->notify)
key->notify (old);
} }
/* {{{1 GThread */ /* {{{1 GThread */

View File

@ -373,9 +373,9 @@ g_private_replace (GPrivate *key,
gpointer old; gpointer old;
old = TlsGetValue (impl); old = TlsGetValue (impl);
TlsSetValue (impl, value);
if (old && key->notify) if (old && key->notify)
key->notify (old); key->notify (old);
TlsSetValue (impl, value);
} }
/* {{{1 GThread */ /* {{{1 GThread */