(root)/
glib-2.79.0/
gio/
tests/
network-monitor-race.c
       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  }