1 /* GLib testing framework examples and tests
3 * Copyright 2014 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
24 volatile gboolean finalized;
26 GType test_threaded_socket_service_get_type (void);
27 typedef GThreadedSocketService TestThreadedSocketService;
28 typedef GThreadedSocketServiceClass TestThreadedSocketServiceClass;
30 G_DEFINE_TYPE (TestThreadedSocketService, test_threaded_socket_service, G_TYPE_THREADED_SOCKET_SERVICE);
33 test_threaded_socket_service_init (TestThreadedSocketService *service)
38 test_threaded_socket_service_finalize (GObject *object)
40 G_OBJECT_CLASS (test_threaded_socket_service_parent_class)->finalize (object);
42 /* Signal the main thread that finalization completed successfully
43 * rather than hanging.
46 g_cond_signal (&cond_712570);
47 g_mutex_unlock (&mutex_712570);
51 test_threaded_socket_service_class_init (TestThreadedSocketServiceClass *klass)
53 GObjectClass *object_class = G_OBJECT_CLASS (klass);
55 object_class->finalize = test_threaded_socket_service_finalize;
59 connection_cb (GThreadedSocketService *service,
60 GSocketConnection *connection,
61 GObject *source_object,
64 /* Block until the main thread has dropped its ref to @service, so that we
65 * will drop the final ref from this thread.
67 g_mutex_lock (&mutex_712570);
69 /* The service should now have 1 ref owned by the current "run"
70 * signal emission, and another added by GThreadedSocketService for
71 * this thread. Both will be dropped after we return.
73 g_assert_cmpint (G_OBJECT (service)->ref_count, ==, 2);
79 client_connected_cb (GObject *client,
83 GMainLoop *loop = user_data;
84 GSocketConnection *conn;
87 conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
88 g_assert_no_error (error);
90 g_object_unref (conn);
91 g_main_loop_quit (loop);
95 test_threaded_712570 (void)
97 GSocketService *service;
98 GSocketAddress *addr, *listening_addr;
100 GSocketClient *client;
101 GError *error = NULL;
104 g_test_bug ("712570");
106 g_mutex_lock (&mutex_712570);
108 service = g_object_new (test_threaded_socket_service_get_type (), NULL);
110 addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
111 g_socket_listener_add_address (G_SOCKET_LISTENER (service),
113 G_SOCKET_TYPE_STREAM,
114 G_SOCKET_PROTOCOL_TCP,
118 g_assert_no_error (error);
119 g_object_unref (addr);
121 g_signal_connect (service, "run", G_CALLBACK (connection_cb), NULL);
123 loop = g_main_loop_new (NULL, FALSE);
125 client = g_socket_client_new ();
126 g_socket_client_connect_async (client,
127 G_SOCKET_CONNECTABLE (listening_addr),
129 client_connected_cb, loop);
130 g_object_unref (client);
131 g_object_unref (listening_addr);
133 g_main_loop_run (loop);
134 g_main_loop_unref (loop);
136 /* Stop the service and then wait for it to asynchronously cancel
137 * its outstanding accept() call (and drop the associated ref).
139 ref_count = G_OBJECT (service)->ref_count;
140 g_socket_service_stop (G_SOCKET_SERVICE (service));
141 while (G_OBJECT (service)->ref_count == ref_count)
142 g_main_context_iteration (NULL, TRUE);
144 /* Drop our ref, then unlock the mutex and wait for the service to be
145 * finalized. (Without the fix for 712570 it would hang forever here.)
147 g_object_unref (service);
150 g_cond_wait (&cond_712570, &mutex_712570);
151 g_mutex_unlock (&mutex_712570);
158 g_test_init (&argc, &argv, NULL);
160 g_test_bug_base ("http://bugzilla.gnome.org/");
162 g_test_add_func ("/socket-listener/threaded/712570", test_threaded_712570);