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