Tizen 2.1 base
[platform/upstream/glib2.0.git] / glib / tests / 642026.c
1 /*
2  * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
3  * Copyright © 2011 Nokia Corporation
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * See the included COPYING file for more information.
11  */
12
13 #define GLIB_DISABLE_DEPRECATION_WARNINGS
14
15 #include <glib.h>
16
17 /* On smcv's laptop, 1e4 iterations didn't always exhibit the bug, but 1e5
18  * iterations exhibited it 10/10 times in practice. YMMV. */
19 #define ITERATIONS 100000
20
21 static GStaticPrivate sp;
22 static GMutex *mutex;
23 static GCond *cond;
24 static guint i;
25
26 static volatile gint freed = 0;
27
28 static void
29 notify (gpointer p)
30 {
31   if (!g_atomic_int_compare_and_exchange (&freed, 0, 1))
32     {
33       g_error ("someone already freed it after %u iterations", i);
34     }
35 }
36
37 static gpointer thread_func (gpointer nil)
38 {
39   /* wait for main thread to reach its g_cond_wait call */
40   g_mutex_lock (mutex);
41
42   g_static_private_set (&sp, &sp, notify);
43   g_cond_broadcast (cond);
44   g_mutex_unlock (mutex);
45
46   return nil;
47 }
48
49 static void
50 testcase (void)
51 {
52   g_test_bug ("642026");
53
54   mutex = g_mutex_new ();
55   cond = g_cond_new ();
56
57   g_mutex_lock (mutex);
58
59   for (i = 0; i < ITERATIONS; i++)
60     {
61       GThread *t1;
62
63       g_static_private_init (&sp);
64       freed = 0;
65
66       t1 = g_thread_create (thread_func, NULL, TRUE, NULL);
67
68       /* wait for t1 to set up its thread-private data */
69       g_cond_wait (cond, mutex);
70
71       /* exercise the bug, by racing with t1 to free the private data */
72       g_static_private_free (&sp);
73       g_thread_join (t1);
74     }
75
76   g_cond_free (cond);
77   g_mutex_unlock (mutex);
78   g_mutex_free (mutex);
79 }
80
81 int
82 main (int argc,
83     char **argv)
84 {
85   g_test_init (&argc, &argv, NULL);
86   g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id=");
87
88   g_test_add_func ("/glib/642026", testcase);
89
90   return g_test_run ();
91 }