File: 642026.c

package info (click to toggle)
glib2.0 2.78.4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,024 kB
  • sloc: ansic: 495,608; xml: 17,404; python: 9,572; perl: 1,144; sh: 1,094; cpp: 487; makefile: 225
file content (104 lines) | stat: -rw-r--r-- 2,674 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
 * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
 * Copyright © 2011 Nokia Corporation
 *
 * SPDX-License-Identifier: LGPL-2.1-or-later
 *
 * 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.1 of the License, or (at your option) any later version.
 *
 * See the included COPYING file for more information.
 */

#ifndef GLIB_DISABLE_DEPRECATION_WARNINGS
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#endif

#include <glib.h>

static GStaticPrivate sp;
static GMutex *mutex;
static GCond *cond;
static guint i;

static gint freed = 0;  /* (atomic) */

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;
}

static void
testcase (void)
{
  /* On smcv's laptop, 1e4 iterations didn't always exhibit the bug, but 1e5
   * iterations exhibited it 10/10 times in practice. YMMV.
   *
   * If running with `-m slow` we want to try hard to reproduce the bug 10/10
   * times. However, as of 2022 this takes around 240s on a CI machine, which
   * is a long time to tie up those resources to verify that a bug fixed 10
   * years ago is still fixed.
   *
   * So if running without `-m slow`, try 100× less hard to reproduce the bug,
   * and rely on the fact that this is run under CI often enough to have a good
   * chance of reproducing the bug in 1% of CI runs. */
  const guint n_iterations = g_test_slow () ? 100000 : 1000;

  g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=642026");

  mutex = g_mutex_new ();
  cond = g_cond_new ();

  g_mutex_lock (mutex);

  for (i = 0; i < n_iterations; i++)
    {
      GThread *t1;

      g_static_private_init (&sp);
      g_atomic_int_set (&freed, 0);

      t1 = g_thread_create (thread_func, NULL, TRUE, NULL);
      g_assert (t1 != 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_add_func ("/glib/642026", testcase);

  return g_test_run ();
}