1/**
2 * Test to make sure late thread initialization works
3 */
4
5#include <dbus/dbus.h>
6#include <dbus/dbus-sysdeps.h>
7#include <stdio.h>
8#include <stdlib.h>
9
10#include <dbus/dbus-internals.h>
11#include <dbus/dbus-connection-internal.h>
12
13static void
14_run_iteration (DBusConnection *conn)
15{
16  DBusPendingCall *echo_pending;
17  DBusPendingCall *dbus_pending;
18  DBusMessage *method;
19  DBusMessage *reply;
20  char *echo = "echo";
21
22  /* send the first message */
23  method = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
24                                         "/org/freedesktop/TestSuite",
25                                         "org.freedesktop.TestSuite",
26                                         "Echo");
27
28  dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL);
29  dbus_connection_send_with_reply (conn, method, &echo_pending, -1);
30  dbus_message_unref (method);
31
32  /* send the second message */
33  method = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
34                                         DBUS_PATH_DBUS,
35                                         "org.freedesktop.Introspectable",
36                                         "Introspect");
37
38  dbus_connection_send_with_reply (conn, method, &dbus_pending, -1);
39  dbus_message_unref (method);
40
41  /* block on the second message (should return immediately) */
42  dbus_pending_call_block (dbus_pending);
43
44  /* block on the first message */
45  /* if it does not return immediately chances
46     are we hit the block in poll bug */
47  dbus_pending_call_block (echo_pending);
48
49  /* check the reply only to make sure we
50     are not getting errors unrelated
51     to the block in poll bug */
52  reply = dbus_pending_call_steal_reply (echo_pending);
53
54  if (reply == NULL)
55    {
56      printf ("Failed: Reply is NULL ***\n");
57      exit (1);
58    }
59
60  if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
61    {
62      printf ("Failed: Reply is error: %s ***\n", dbus_message_get_error_name (reply));
63      exit (1);
64    }
65
66  dbus_message_unref (reply);
67  dbus_pending_call_unref (dbus_pending);
68  dbus_pending_call_unref (echo_pending);
69
70}
71static void
72check_mutex_lock (DBusMutex *mutex1,
73                  DBusMutex *mutex2,
74                  dbus_bool_t is_same)
75{
76  _dbus_assert (mutex1 != NULL);
77  _dbus_assert (mutex2 != NULL);
78
79  if (is_same)
80    {
81      _dbus_assert (mutex1 == mutex2);
82    }
83  else
84    {
85      _dbus_assert (mutex1 != mutex2);
86    }
87}
88
89static void
90check_condvar_lock (DBusCondVar *condvar1,
91                    DBusCondVar *condvar2,
92                    dbus_bool_t is_same)
93{
94  _dbus_assert (condvar1 != NULL);
95  _dbus_assert (condvar2 != NULL);
96
97  if (is_same)
98    {
99      _dbus_assert (condvar1 == condvar2);
100    }
101  else
102    {
103      _dbus_assert (condvar1 != condvar2);
104    }
105}
106
107
108int
109main (int argc, char *argv[])
110{
111  DBusMessage *method;
112  DBusConnection *conn;
113  DBusError error;
114  DBusMutex *mutex1, *dispatch_mutex1, *io_path_mutex1;
115  DBusCondVar *dispatch_cond1, *io_path_cond1;
116  DBusMutex *mutex2, *dispatch_mutex2, *io_path_mutex2;
117  DBusCondVar *dispatch_cond2, *io_path_cond2;
118
119  printf ("*** Testing late thread init\n");
120
121  dbus_error_init (&error);
122
123  conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
124
125  _dbus_connection_test_get_locks (conn, &mutex1,
126                                         &dispatch_mutex1,
127                                         &io_path_mutex1,
128                                         &dispatch_cond1,
129                                         &io_path_cond1);
130  _run_iteration (conn);
131  _dbus_connection_test_get_locks (conn, &mutex2,
132                                         &dispatch_mutex2,
133                                         &io_path_mutex2,
134                                         &dispatch_cond2,
135                                         &io_path_cond2);
136
137  check_mutex_lock (mutex1, mutex2, TRUE);
138  check_mutex_lock (dispatch_mutex1, dispatch_mutex2, TRUE);
139  check_mutex_lock (io_path_mutex1, io_path_mutex2, TRUE);
140  check_condvar_lock (dispatch_cond1, dispatch_cond2, TRUE);
141  check_condvar_lock (io_path_cond1, io_path_cond2, TRUE);
142
143  dbus_threads_init_default ();
144
145  _dbus_connection_test_get_locks (conn, &mutex1,
146                                         &dispatch_mutex1,
147                                         &io_path_mutex1,
148                                         &dispatch_cond1,
149                                         &io_path_cond1);
150
151  check_mutex_lock (mutex1, mutex2, FALSE);
152  check_mutex_lock (dispatch_mutex1, dispatch_mutex2, FALSE);
153  check_mutex_lock (io_path_mutex1, io_path_mutex2, FALSE);
154  check_condvar_lock (dispatch_cond1, dispatch_cond2, FALSE);
155  check_condvar_lock (io_path_cond1, io_path_cond2, FALSE);
156
157  _run_iteration (conn);
158  _dbus_connection_test_get_locks (conn, &mutex2,
159                                         &dispatch_mutex2,
160                                         &io_path_mutex2,
161                                         &dispatch_cond2,
162                                         &io_path_cond2);
163
164  check_mutex_lock (mutex1, mutex2, TRUE);
165  check_mutex_lock (dispatch_mutex1, dispatch_mutex2, TRUE);
166  check_mutex_lock (io_path_mutex1, io_path_mutex2, TRUE);
167  check_condvar_lock (dispatch_cond1, dispatch_cond2, TRUE);
168  check_condvar_lock (io_path_cond1, io_path_cond2, TRUE);
169
170  method = dbus_message_new_method_call ("org.freedesktop.TestSuiteEchoService",
171                                         "/org/freedesktop/TestSuite",
172                                         "org.freedesktop.TestSuite",
173                                         "Exit");
174  dbus_connection_send (conn, method, NULL);
175  dbus_message_unref (method);
176
177  printf ("Success ***\n");
178  exit (0);
179}
180