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
23 static gboolean
quit_loop(gpointer user_data)24 quit_loop (gpointer user_data)
25 {
26 g_main_loop_quit (user_data);
27
28 return FALSE;
29 }
30
31 static gpointer
thread_func(gpointer user_data)32 thread_func (gpointer user_data)
33 {
34 g_network_monitor_get_default ();
35 g_timeout_add (100, quit_loop, user_data);
36
37 return NULL;
38 }
39
40 static gboolean
call_func(gpointer user_data)41 call_func (gpointer user_data)
42 {
43 GThread *thread;
44
45 thread = g_thread_new (NULL, thread_func, 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. */
56 static void
test_network_monitor(void)57 test_network_monitor (void)
58 {
59 guint ii;
60
61 g_test_bug ("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 (1, call_func, main_loop);
69 g_main_loop_run (main_loop);
70 g_main_loop_unref (main_loop);
71
72 return;
73 }
74
75 for (ii = 0; ii < MAX_RUNS; ii++)
76 {
77 g_test_trap_subprocess (NULL,
78 0,
79 G_TEST_SUBPROCESS_INHERIT_STDOUT |
80 G_TEST_SUBPROCESS_INHERIT_STDERR);
81 g_test_trap_assert_passed ();
82 }
83 }
84
85 int
main(int argc,char * argv[])86 main (int argc, char *argv[])
87 {
88 g_test_init (&argc, &argv, NULL);
89 g_test_bug_base ("https://bugzilla.gnome.org/show_bug.cgi?id=");
90
91 g_test_add_func ("/network-monitor/create-in-thread",
92 test_network_monitor);
93
94 return g_test_run ();
95 }
96