(root)/
glib-2.79.0/
glib/
tests/
642026.c
       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  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    /* 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    const guint n_iterations = g_test_slow () ? 100000 : 1000;
      64  
      65    g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=642026");
      66  
      67    mutex = g_mutex_new ();
      68    cond = g_cond_new ();
      69  
      70    g_mutex_lock (mutex);
      71  
      72    for (i = 0; i < n_iterations; i++)
      73      {
      74        GThread *t1;
      75  
      76        g_static_private_init (&sp);
      77        g_atomic_int_set (&freed, 0);
      78  
      79        t1 = g_thread_create (thread_func, NULL, TRUE, NULL);
      80        g_assert (t1 != NULL);
      81  
      82        /* wait for t1 to set up its thread-private data */
      83        g_cond_wait (cond, mutex);
      84  
      85        /* exercise the bug, by racing with t1 to free the private data */
      86        g_static_private_free (&sp);
      87        g_thread_join (t1);
      88      }
      89  
      90    g_cond_free (cond);
      91    g_mutex_unlock (mutex);
      92    g_mutex_free (mutex);
      93  }
      94  
      95  int
      96  main (int argc,
      97      char **argv)
      98  {
      99    g_test_init (&argc, &argv, NULL);
     100  
     101    g_test_add_func ("/glib/642026", testcase);
     102  
     103    return g_test_run ();
     104  }