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 
14 static void
_run_iteration(DBusConnection * conn)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 }
72 static void
check_mutex_lock(DBusMutex * mutex1,DBusMutex * mutex2,dbus_bool_t is_same)73 check_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 
90 static void
check_condvar_lock(DBusCondVar * condvar1,DBusCondVar * condvar2,dbus_bool_t is_same)91 check_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 
109 int
main(int argc,char * argv[])110 main (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