• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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