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 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 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