1 /**
2 * Test to make sure we don't get stuck polling a dbus connection
3 * which has no data on the socket. This was an issue where
4 * one pending call would read all the data off the bus
5 * and the second pending call would not check to see
6 * if its data had already been read before polling the connection
7 * and blocking.
8 **/
9
10 #include <dbus/dbus.h>
11 #include <dbus/dbus-sysdeps.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14
15 static void
_run_iteration(DBusConnection * conn)16 _run_iteration (DBusConnection *conn)
17 {
18 DBusPendingCall *echo_pending;
19 DBusPendingCall *dbus_pending;
20 DBusMessage *method;
21 DBusMessage *reply;
22 char *echo = "echo";
23
24 /* send the first message */
25 method = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteEchoService",
26 "/org/freedesktop/TestSuite",
27 "org.freedesktop.TestSuite",
28 "Echo");
29
30 dbus_message_append_args (method, DBUS_TYPE_STRING, &echo, NULL);
31 dbus_connection_send_with_reply (conn, method, &echo_pending, -1);
32 dbus_message_unref (method);
33
34 /* send the second message */
35 method = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
36 DBUS_PATH_DBUS,
37 "org.freedesktop.Introspectable",
38 "Introspect");
39
40 dbus_connection_send_with_reply (conn, method, &dbus_pending, -1);
41 dbus_message_unref (method);
42
43 /* block on the second message (should return immediately) */
44 dbus_pending_call_block (dbus_pending);
45
46 /* block on the first message */
47 /* if it does not return immediately chances
48 are we hit the block in poll bug */
49 dbus_pending_call_block (echo_pending);
50
51 /* check the reply only to make sure we
52 are not getting errors unrelated
53 to the block in poll bug */
54 reply = dbus_pending_call_steal_reply (echo_pending);
55
56 if (reply == NULL)
57 {
58 printf ("Failed: Reply is NULL ***\n");
59 exit (1);
60 }
61
62 if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
63 {
64 printf ("Failed: Reply is error: %s ***\n", dbus_message_get_error_name (reply));
65 exit (1);
66 }
67
68 dbus_message_unref (reply);
69 dbus_pending_call_unref (dbus_pending);
70 dbus_pending_call_unref (echo_pending);
71
72 }
73
74 int
main(int argc,char * argv[])75 main (int argc, char *argv[])
76 {
77 long start_tv_sec, start_tv_usec;
78 long end_tv_sec, end_tv_usec;
79 int i;
80 DBusMessage *method;
81 DBusConnection *conn;
82 DBusError error;
83
84 /* Time each iteration and make sure it doesn't take more than 5 seconds
85 to complete. Outside influences may cause connections to take longer
86 but if it does and we are stuck in a poll call then we know the
87 stuck in poll bug has come back to haunt us */
88
89 printf ("*** Testing stuck in poll\n");
90
91 dbus_error_init (&error);
92
93 conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
94
95 /* run 100 times to make sure */
96 for (i = 0; i < 100; i++)
97 {
98 long delta;
99
100 _dbus_get_current_time (&start_tv_sec, &start_tv_usec);
101 _run_iteration (conn);
102 _dbus_get_current_time (&end_tv_sec, &end_tv_usec);
103
104 /* we just care about seconds */
105 delta = end_tv_sec - start_tv_sec;
106 printf ("Iter %i: %lis\n", i, delta);
107 if (delta >= 5)
108 {
109 printf ("Failed: looks like we might have been be stuck in poll ***\n");
110 exit (1);
111 }
112 }
113
114 method = dbus_message_new_method_call ("org.freedesktop.TestSuiteEchoService",
115 "/org/freedesktop/TestSuite",
116 "org.freedesktop.TestSuite",
117 "Exit");
118 dbus_connection_send (conn, method, NULL);
119 dbus_message_unref (method);
120
121 printf ("Success ***\n");
122 exit (0);
123 }
124