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 |
24 | quit_loop (gpointer user_data) |
25 | { |
26 | g_main_loop_quit (loop: user_data); |
27 | |
28 | return FALSE; |
29 | } |
30 | |
31 | static gpointer |
32 | thread_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 | |
40 | static gboolean |
41 | call_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. */ |
56 | static void |
57 | test_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 | |
85 | int |
86 | main (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 | |