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