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