Branch data Line data Source code
1 : : /* 2 : : * Author: Simon McVittie <simon.mcvittie@collabora.co.uk> 3 : : * Copyright © 2011 Nokia Corporation 4 : : * 5 : : * SPDX-License-Identifier: LGPL-2.1-or-later 6 : : * 7 : : * This program is free software; you can redistribute it and/or 8 : : * modify it under the terms of the GNU Lesser General Public 9 : : * License as published by the Free Software Foundation; either 10 : : * version 2.1 of the License, or (at your option) any later version. 11 : : * 12 : : * See the included COPYING file for more information. 13 : : */ 14 : : 15 : : #ifndef GLIB_DISABLE_DEPRECATION_WARNINGS 16 : : #define GLIB_DISABLE_DEPRECATION_WARNINGS 17 : : #endif 18 : : 19 : : #include <glib.h> 20 : : 21 : : static GStaticPrivate sp; 22 : : static GMutex *mutex; 23 : : static GCond *cond; 24 : : static guint i; 25 : : 26 : : static gint freed = 0; /* (atomic) */ 27 : : 28 : : static void 29 : 2000 : notify (gpointer p) 30 : : { 31 [ - + ]: 2000 : if (!g_atomic_int_compare_and_exchange (&freed, 0, 1)) 32 : : { 33 : 0 : g_error ("someone already freed it after %u iterations", i); 34 : : } 35 : 2000 : } 36 : : 37 : 2000 : static gpointer thread_func (gpointer nil) 38 : : { 39 : : /* wait for main thread to reach its g_cond_wait call */ 40 : 2000 : g_mutex_lock (mutex); 41 : : 42 : 2000 : g_static_private_set (&sp, &sp, notify); 43 : 2000 : g_cond_broadcast (cond); 44 : 2000 : g_mutex_unlock (mutex); 45 : : 46 : 2000 : return nil; 47 : : } 48 : : 49 : : static void 50 : 2 : testcase (void) 51 : : { 52 : : /* On smcv's laptop, 1e4 iterations didn't always exhibit the bug, but 1e5 53 : : * iterations exhibited it 10/10 times in practice. YMMV. 54 : : * 55 : : * If running with `-m slow` we want to try hard to reproduce the bug 10/10 56 : : * times. However, as of 2022 this takes around 240s on a CI machine, which 57 : : * is a long time to tie up those resources to verify that a bug fixed 10 58 : : * years ago is still fixed. 59 : : * 60 : : * So if running without `-m slow`, try 100× less hard to reproduce the bug, 61 : : * and rely on the fact that this is run under CI often enough to have a good 62 : : * chance of reproducing the bug in 1% of CI runs. */ 63 [ - + ]: 2 : const guint n_iterations = g_test_slow () ? 100000 : 1000; 64 : : 65 : 2 : g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=642026"); 66 : : 67 : 2 : mutex = g_mutex_new (); 68 : 2 : cond = g_cond_new (); 69 : : 70 : 2 : g_mutex_lock (mutex); 71 : : 72 [ + + ]: 2002 : for (i = 0; i < n_iterations; i++) 73 : : { 74 : : GThread *t1; 75 : : 76 : 2000 : g_static_private_init (&sp); 77 : 2000 : g_atomic_int_set (&freed, 0); 78 : : 79 : 2000 : t1 = g_thread_create (thread_func, NULL, TRUE, NULL); 80 : 2000 : g_assert (t1 != NULL); 81 : : 82 : : /* wait for t1 to set up its thread-private data */ 83 : 2000 : g_cond_wait (cond, mutex); 84 : : 85 : : /* exercise the bug, by racing with t1 to free the private data */ 86 : 2000 : g_static_private_free (&sp); 87 : 2000 : g_thread_join (t1); 88 : : } 89 : : 90 : 2 : g_cond_free (cond); 91 : 2 : g_mutex_unlock (mutex); 92 : 2 : g_mutex_free (mutex); 93 : 2 : } 94 : : 95 : : int 96 : 2 : main (int argc, 97 : : char **argv) 98 : : { 99 : 2 : g_test_init (&argc, &argv, NULL); 100 : : 101 : 2 : g_test_add_func ("/glib/642026", testcase); 102 : : 103 : 2 : return g_test_run (); 104 : : }