1/*
2 * Copyright (C) 2018 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1 of the
7 * licence, or (at your option) any later version.
8 *
9 * This is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 * License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <glib/glib.h>
19#include <gio/gio.h>
20
21#define MAX_RUNS 20
22
23static gboolean
24quit_loop (gpointer user_data)
25{
26 g_main_loop_quit (loop: user_data);
27
28 return FALSE;
29}
30
31static gpointer
32thread_func (gpointer user_data)
33{
34 g_network_monitor_get_default ();
35 g_timeout_add (interval: 100, function: quit_loop, data: user_data);
36
37 return NULL;
38}
39
40static gboolean
41call_func (gpointer user_data)
42{
43 GThread *thread;
44
45 thread = g_thread_new (NULL, func: thread_func, data: user_data);
46 g_thread_unref (thread);
47
48 return FALSE;
49}
50
51/* Test that calling g_network_monitor_get_default() in a thread doesn’t cause
52 * a crash. This is a probabilistic test; since it’s testing a race condition,
53 * it can’t deterministically reproduce the problem. The threading has to
54 * happen in subprocesses, since the result of g_network_monitor_get_default()
55 * is unavoidably cached once created. */
56static void
57test_network_monitor (void)
58{
59 guint ii;
60
61 g_test_bug (bug_uri_snippet: "793727");
62
63 if (g_test_subprocess ())
64 {
65 GMainLoop *main_loop;
66
67 main_loop = g_main_loop_new (NULL, FALSE);
68 g_timeout_add (interval: 1, function: call_func, data: main_loop);
69 g_main_loop_run (loop: main_loop);
70 g_main_loop_unref (loop: main_loop);
71
72 return;
73 }
74
75 for (ii = 0; ii < MAX_RUNS; ii++)
76 {
77 g_test_trap_subprocess (NULL,
78 usec_timeout: 0,
79 test_flags: G_TEST_SUBPROCESS_INHERIT_STDOUT |
80 G_TEST_SUBPROCESS_INHERIT_STDERR);
81 g_test_trap_assert_passed ();
82 }
83}
84
85int
86main (int argc, char *argv[])
87{
88 g_test_init (argc: &argc, argv: &argv, NULL);
89 g_test_bug_base (uri_pattern: "https://bugzilla.gnome.org/show_bug.cgi?id=");
90
91 g_test_add_func (testpath: "/network-monitor/create-in-thread",
92 test_func: test_network_monitor);
93
94 return g_test_run ();
95}
96

source code of gtk/subprojects/glib/gio/tests/network-monitor-race.c