• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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