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