From 9a36b758238bbb09c91b3a4863a2a8e2f8765dec Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 24 May 2011 11:04:42 +0100 Subject: [PATCH] Add a regression test for GNOME#642026 Bug: https://bugzilla.gnome.org/show_bug.cgi?id=642026 Bug-NB: NB#257512 --- gthread/tests/642026.c | 91 +++++++++++++++++++++++++++++++++++++++ gthread/tests/Makefile.am | 3 ++ 2 files changed, 94 insertions(+) create mode 100644 gthread/tests/642026.c diff --git a/gthread/tests/642026.c b/gthread/tests/642026.c new file mode 100644 index 000000000..a056edd25 --- /dev/null +++ b/gthread/tests/642026.c @@ -0,0 +1,91 @@ +/* + * Author: Simon McVittie + * Copyright © 2011 Nokia Corporation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * See the included COPYING file for more information. + */ + +#include + +/* On smcv's laptop, 1e4 iterations didn't always exhibit the bug, but 1e5 + * iterations exhibited it 10/10 times in practice. YMMV. */ +#define ITERATIONS 100000 + +static GStaticPrivate sp; +static GMutex *mutex; +static GCond *cond; +static guint i; + +static volatile gint freed = 0; + +static void +notify (gpointer p) +{ + if (!g_atomic_int_compare_and_exchange (&freed, 0, 1)) + { + g_error ("someone already freed it after %u iterations", i); + } +} + +static gpointer thread_func (gpointer nil) +{ + /* wait for main thread to reach its g_cond_wait call */ + g_mutex_lock (mutex); + + g_static_private_set (&sp, &sp, notify); + g_cond_broadcast (cond); + g_mutex_unlock (mutex); + + return nil; +} + +void +testcase (void) +{ + g_test_bug ("642026"); + + g_thread_init (NULL); + + mutex = g_mutex_new (); + cond = g_cond_new (); + + g_mutex_lock (mutex); + + for (i = 0; i < ITERATIONS; i++) + { + GThread *t1; + + g_static_private_init (&sp); + freed = 0; + + t1 = g_thread_create (thread_func, NULL, TRUE, NULL); + + /* wait for t1 to set up its thread-private data */ + g_cond_wait (cond, mutex); + + /* exercise the bug, by racing with t1 to free the private data */ + g_static_private_free (&sp); + g_thread_join (t1); + } + + g_cond_free (cond); + g_mutex_unlock (mutex); + g_mutex_free (mutex); +} + +int +main (int argc, + char **argv) +{ + g_test_init (&argc, &argv, NULL); + g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id="); + + g_test_add_func ("/glib/642026", testcase); + + return g_test_run (); +} diff --git a/gthread/tests/Makefile.am b/gthread/tests/Makefile.am index 387098ad8..4edcf1fb2 100644 --- a/gthread/tests/Makefile.am +++ b/gthread/tests/Makefile.am @@ -9,6 +9,9 @@ progs_ldadd = $(top_builddir)/glib/libglib-2.0.la \ TEST_PROGS += 1bit-mutex 1bit_mutex_LDADD = $(progs_ldadd) $(top_builddir)/gthread/libgthread-2.0.la +TEST_PROGS += 642026 +642026_LDADD = $(progs_ldadd) + TEST_PROGS += 1bit-emufutex 1bit_emufutex_SOURCES = 1bit-mutex.c 1bit_emufutex_CFLAGS = -DTEST_EMULATED_FUTEX