From dbdea921b5967ed25b24a9e5af5d6a3db54c5ec7 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 26 Nov 2004 01:53:13 +0000 Subject: 2004-11-25 Havoc Pennington The primary change here is to always write() once before adding the write watch, which gives us about a 10% performance increase. * dbus/dbus-transport-unix.c: a number of modifications to cope with removing messages_pending (check_write_watch): properly handle DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of messages_pending stuff (check_read_watch): properly handle WAITING_FOR_MEMORY and AUTHENTICATED cases (unix_handle_watch): after writing, see if the write watch can be removed (unix_do_iteration): assert that write_watch/read_watch are non-NULL rather than testing that they aren't, since they aren't allowed to be NULL. check_write_watch() at the end so we add the watch if we did not finish writing (e.g. got EAGAIN) * dbus/dbus-transport-protected.h: remove messages_pending call, since it resulted in too much inefficient watch adding/removing; instead we now require that the transport user does an iteration after queueing outgoing messages, and after trying the first write() we add a write watch if we got EAGAIN or exceeded our max bytes to write per iteration setting * dbus/dbus-string.c (_dbus_string_validate_signature): add this function * dbus/dbus-server-unix.c (unix_finalize): the socket name was freed and then accessed, valgrind flagged this bug, fix it * dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken as the last valid field plus 1, where really it is equal to the last valid field. Corrects some message corruption issues. * dbus/dbus-mainloop.c: verbosity changes * dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM instead of aborting in one of the test codepaths * dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that caused not printing the pid ever again if a verbose was missing the newline at the end (_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE * dbus/dbus-connection.c: verbosity changes; (dbus_connection_has_messages_to_send): new function (_dbus_connection_message_sent): no longer call transport->messages_pending (_dbus_connection_send_preallocated_unlocked): do one iteration to try to write() immediately, so we can avoid the write watch. This is the core purpose of this patchset (_dbus_connection_get_dispatch_status_unlocked): if disconnected, dump the outgoing message queue, so nobody will get confused trying to send them or thinking stuff is pending to be sent * bus/test.c: verbosity changes * bus/driver.c: verbosity/assertion changes * bus/dispatch.c: a bunch of little tweaks to get it working again because this patchset changes when/where you need to block. --- ChangeLog | 63 +++++++++++++ bus/dispatch.c | 139 ++++++++++++++++++++-------- bus/driver.c | 9 +- bus/test.c | 10 +- dbus/dbus-connection-internal.h | 2 +- dbus/dbus-connection.c | 200 ++++++++++++++++++++++++++++++++-------- dbus/dbus-connection.h | 1 + dbus/dbus-internals.c | 23 ++--- dbus/dbus-keyring.c | 2 +- dbus/dbus-mainloop.c | 31 ++++++- dbus/dbus-message.c | 111 +++++++++++++++++++--- dbus/dbus-server-unix.c | 5 +- dbus/dbus-string.c | 126 +++++++++++++++++++++++-- dbus/dbus-string.h | 3 + dbus/dbus-sysdeps.c | 3 + dbus/dbus-transport-protected.h | 9 +- dbus/dbus-transport-unix.c | 167 ++++++++++++++++++++++++--------- dbus/dbus-transport.c | 27 ------ dbus/dbus-transport.h | 2 - dbus/dbus-watch.c | 27 +++++- doc/TODO | 3 + test/glib/test-profile.c | 16 +++- 22 files changed, 772 insertions(+), 207 deletions(-) diff --git a/ChangeLog b/ChangeLog index f85dd6b9..c9f42f4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,66 @@ +2004-11-25 Havoc Pennington + + The primary change here is to always write() once before adding + the write watch, which gives us about a 10% performance increase. + + * dbus/dbus-transport-unix.c: a number of modifications to cope + with removing messages_pending + (check_write_watch): properly handle + DBUS_AUTH_STATE_WAITING_FOR_MEMORY; adapt to removal of + messages_pending stuff + (check_read_watch): properly handle WAITING_FOR_MEMORY and + AUTHENTICATED cases + (unix_handle_watch): after writing, see if the write watch can be + removed + (unix_do_iteration): assert that write_watch/read_watch are + non-NULL rather than testing that they aren't, since they + aren't allowed to be NULL. check_write_watch() at the end so + we add the watch if we did not finish writing (e.g. got EAGAIN) + + * dbus/dbus-transport-protected.h: remove messages_pending call, + since it resulted in too much inefficient watch adding/removing; + instead we now require that the transport user does an iteration + after queueing outgoing messages, and after trying the first + write() we add a write watch if we got EAGAIN or exceeded our + max bytes to write per iteration setting + + * dbus/dbus-string.c (_dbus_string_validate_signature): add this + function + + * dbus/dbus-server-unix.c (unix_finalize): the socket name was + freed and then accessed, valgrind flagged this bug, fix it + + * dbus/dbus-message.c: fix several bugs where HEADER_FIELD_LAST was taken + as the last valid field plus 1, where really it is equal to the + last valid field. Corrects some message corruption issues. + + * dbus/dbus-mainloop.c: verbosity changes + + * dbus/dbus-keyring.c (_dbus_keyring_new_homedir): handle OOM + instead of aborting in one of the test codepaths + + * dbus/dbus-internals.c (_dbus_verbose_real): fix a bug that + caused not printing the pid ever again if a verbose was missing + the newline at the end + (_dbus_header_field_to_string): add HEADER_FIELD_SIGNATURE + + * dbus/dbus-connection.c: verbosity changes; + (dbus_connection_has_messages_to_send): new function + (_dbus_connection_message_sent): no longer call transport->messages_pending + (_dbus_connection_send_preallocated_unlocked): do one iteration to + try to write() immediately, so we can avoid the write watch. This + is the core purpose of this patchset + (_dbus_connection_get_dispatch_status_unlocked): if disconnected, + dump the outgoing message queue, so nobody will get confused + trying to send them or thinking stuff is pending to be sent + + * bus/test.c: verbosity changes + + * bus/driver.c: verbosity/assertion changes + + * bus/dispatch.c: a bunch of little tweaks to get it working again + because this patchset changes when/where you need to block. + 2004-11-23 Havoc Pennington * test/glib/test-profile.c: modify to accept a plain_sockets diff --git a/bus/dispatch.c b/bus/dispatch.c index 3cd1c3e4..e04d2895 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -2,7 +2,7 @@ /* dispatch.c Message dispatcher * * Copyright (C) 2003 CodeFactory AB - * Copyright (C) 2003 Red Hat, Inc. + * Copyright (C) 2003, 2004 Red Hat, Inc. * Copyright (C) 2004 Imendio HB * * Licensed under the Academic Free License version 2.1 @@ -401,6 +401,12 @@ bus_dispatch_remove_connection (DBusConnection *connection) #include +/* This is used to know whether we need to block in order to finish + * sending a message, or whether the initial dbus_connection_send() + * already flushed the queue. + */ +#define SEND_PENDING(connection) (dbus_connection_has_messages_to_send (connection)) + typedef dbus_bool_t (* Check1Func) (BusContext *context); typedef dbus_bool_t (* Check2Func) (BusContext *context, DBusConnection *connection); @@ -409,8 +415,11 @@ static dbus_bool_t check_no_leftovers (BusContext *context); static void block_connection_until_message_from_bus (BusContext *context, - DBusConnection *connection) + DBusConnection *connection, + const char *what_is_expected) { + _dbus_verbose ("expecting: %s\n", what_is_expected); + while (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_COMPLETE && dbus_connection_get_is_connected (connection)) @@ -420,6 +429,20 @@ block_connection_until_message_from_bus (BusContext *context, } } +static void +spin_connection_until_authenticated (BusContext *context, + DBusConnection *connection) +{ + _dbus_verbose ("Spinning to auth connection %p\n", connection); + while (!dbus_connection_get_is_authenticated (connection) && + dbus_connection_get_is_connected (connection)) + { + bus_test_run_bus_loop (context, FALSE); + bus_test_run_clients_loop (FALSE); + } + _dbus_verbose (" ... done spinning to auth connection %p\n", connection); +} + /* compensate for fact that pop_message() can return #NULL due to OOM */ static DBusMessage* pop_message_waiting_for_memory (DBusConnection *connection) @@ -737,24 +760,46 @@ check_hello_message (BusContext *context, if (message == NULL) return TRUE; + dbus_connection_ref (connection); /* because we may get disconnected */ + if (!dbus_connection_send (connection, message, &serial)) { dbus_message_unref (message); + dbus_connection_unref (connection); return TRUE; } + _dbus_assert (dbus_message_has_signature (message, "")); + dbus_message_unref (message); message = NULL; + if (!dbus_connection_get_is_connected (connection)) + { + _dbus_verbose ("connection was disconnected (presumably auth failed)\n"); + + dbus_connection_unref (connection); + + return TRUE; + } + /* send our message */ - bus_test_run_clients_loop (TRUE); + bus_test_run_clients_loop (SEND_PENDING (connection)); - dbus_connection_ref (connection); /* because we may get disconnected */ - block_connection_until_message_from_bus (context, connection); + if (!dbus_connection_get_is_connected (connection)) + { + _dbus_verbose ("connection was disconnected (presumably auth failed)\n"); + + dbus_connection_unref (connection); + + return TRUE; + } + + block_connection_until_message_from_bus (context, connection, "reply to Hello"); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected (presumably auth failed)\n"); dbus_connection_unref (connection); @@ -945,14 +990,14 @@ check_double_hello_message (BusContext *context, message = NULL; /* send our message */ - bus_test_run_clients_loop (TRUE); + bus_test_run_clients_loop (SEND_PENDING (connection)); dbus_connection_ref (connection); /* because we may get disconnected */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply to Hello"); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); dbus_connection_unref (connection); @@ -1044,17 +1089,17 @@ check_get_connection_unix_user (BusContext *context, } /* send our message */ - bus_test_run_clients_loop (TRUE); + bus_test_run_clients_loop (SEND_PENDING (connection)); dbus_message_unref (message); message = NULL; dbus_connection_ref (connection); /* because we may get disconnected */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixUser"); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); dbus_connection_unref (connection); @@ -1181,17 +1226,17 @@ check_get_connection_unix_process_id (BusContext *context, } /* send our message */ - bus_test_run_clients_loop (TRUE); + bus_test_run_clients_loop (SEND_PENDING (connection)); dbus_message_unref (message); message = NULL; dbus_connection_ref (connection); /* because we may get disconnected */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixProcessID"); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); dbus_connection_unref (connection); @@ -1331,15 +1376,25 @@ check_add_match_all (BusContext *context, dbus_message_unref (message); message = NULL; + dbus_connection_ref (connection); /* because we may get disconnected */ + /* send our message */ - bus_test_run_clients_loop (TRUE); + bus_test_run_clients_loop (SEND_PENDING (connection)); - dbus_connection_ref (connection); /* because we may get disconnected */ - block_connection_until_message_from_bus (context, connection); + if (!dbus_connection_get_is_connected (connection)) + { + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); + + dbus_connection_unref (connection); + + return TRUE; + } + + block_connection_until_message_from_bus (context, connection, "reply to AddMatch"); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); dbus_connection_unref (connection); @@ -1435,6 +1490,8 @@ check_hello_connection (BusContext *context) return TRUE; } + spin_connection_until_authenticated (context, connection); + if (!check_hello_message (context, connection)) return FALSE; @@ -1496,12 +1553,12 @@ check_nonexistent_service_activation (BusContext *context, message = NULL; bus_test_run_everything (context); - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply to ActivateService on nonexistent"); bus_test_run_everything (context); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); return TRUE; } @@ -1590,12 +1647,12 @@ check_nonexistent_service_auto_activation (BusContext *context, message = NULL; bus_test_run_everything (context); - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply to Echo"); bus_test_run_everything (context); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); return TRUE; } @@ -2116,7 +2173,7 @@ check_send_exit_to_service (BusContext *context, message = NULL; /* send message */ - bus_test_run_clients_loop (TRUE); + bus_test_run_clients_loop (SEND_PENDING (connection)); /* read it in and write it out to test service */ bus_test_run_bus_loop (context, FALSE); @@ -2134,7 +2191,7 @@ check_send_exit_to_service (BusContext *context, if (!got_error) { /* If no error, wait for the test service to exit */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "test service to exit"); bus_test_run_everything (context); } @@ -2394,13 +2451,13 @@ check_existent_service_activation (BusContext *context, /* now wait for the message bus to hear back from the activated * service. */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "activated service to connect"); bus_test_run_everything (context); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); return TRUE; } @@ -2458,7 +2515,7 @@ check_existent_service_activation (BusContext *context, message = NULL; /* We may need to block here for the test service to exit or finish up */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "test service to exit or finish up"); message = dbus_connection_borrow_message (connection); if (message == NULL) @@ -2514,7 +2571,7 @@ check_existent_service_activation (BusContext *context, */ if (message_kind != GOT_ERROR) { - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "error about service exiting"); /* and process everything again */ bus_test_run_everything (context); @@ -2608,12 +2665,12 @@ check_segfault_service_activation (BusContext *context, message = NULL; bus_test_run_everything (context); - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply to activating segfault service"); bus_test_run_everything (context); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); return TRUE; } @@ -2703,12 +2760,12 @@ check_segfault_service_auto_activation (BusContext *context, message = NULL; bus_test_run_everything (context); - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply to Echo on segfault service"); bus_test_run_everything (context); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); return TRUE; } @@ -2814,12 +2871,12 @@ check_existent_service_auto_activation (BusContext *context, /* now wait for the message bus to hear back from the activated * service. */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply to Echo on existent service"); bus_test_run_everything (context); if (!dbus_connection_get_is_connected (connection)) { - _dbus_verbose ("connection was disconnected\n"); + _dbus_verbose ("connection was disconnected: %s %d\n", _DBUS_FUNCTION_NAME, __LINE__); return TRUE; } @@ -2849,7 +2906,7 @@ check_existent_service_auto_activation (BusContext *context, message = NULL; /* We may need to block here for the test service to exit or finish up */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "service to exit"); /* Should get a service creation notification for the activated * service name, or a service deletion on the base service name @@ -2924,7 +2981,7 @@ check_existent_service_auto_activation (BusContext *context, /* Note: if this test is run in OOM mode, it will block when the bus * doesn't send a reply due to OOM. */ - block_connection_until_message_from_bus (context, connection); + block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation"); message = pop_message_waiting_for_memory (connection); if (message == NULL) @@ -3064,6 +3121,8 @@ bus_dispatch_test (const DBusString *test_data_dir) if (!bus_setup_debug_client (foo)) _dbus_assert_not_reached ("could not set up connection"); + spin_connection_until_authenticated (context, foo); + if (!check_hello_message (context, foo)) _dbus_assert_not_reached ("hello message failed"); @@ -3080,6 +3139,8 @@ bus_dispatch_test (const DBusString *test_data_dir) if (!bus_setup_debug_client (bar)) _dbus_assert_not_reached ("could not set up connection"); + spin_connection_until_authenticated (context, bar); + if (!check_hello_message (context, bar)) _dbus_assert_not_reached ("hello message failed"); @@ -3093,6 +3154,8 @@ bus_dispatch_test (const DBusString *test_data_dir) if (!bus_setup_debug_client (baz)) _dbus_assert_not_reached ("could not set up connection"); + spin_connection_until_authenticated (context, baz); + if (!check_hello_message (context, baz)) _dbus_assert_not_reached ("hello message failed"); @@ -3176,6 +3239,8 @@ bus_dispatch_sha1_test (const DBusString *test_data_dir) if (!bus_setup_debug_client (foo)) _dbus_assert_not_reached ("could not set up connection"); + spin_connection_until_authenticated (context, foo); + if (!check_hello_message (context, foo)) _dbus_assert_not_reached ("hello message failed"); diff --git a/bus/driver.c b/bus/driver.c index b426912f..dc640396 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -2,7 +2,7 @@ /* driver.c Bus client (driver) * * Copyright (C) 2003 CodeFactory AB - * Copyright (C) 2003 Red Hat, Inc. + * Copyright (C) 2003, 2004 Red Hat, Inc. * * Licensed under the Academic Free License version 2.1 * @@ -51,7 +51,8 @@ bus_driver_send_service_owner_changed (const char *service_name, _DBUS_ASSERT_ERROR_IS_CLEAR (error); - _dbus_verbose ("sending service owner changed: %s [%s -> %s]", service_name, + _dbus_verbose ("sending service owner changed: %s [%s -> %s]\n", + service_name, old_owner ? old_owner : null_service, new_owner ? new_owner : null_service); @@ -75,6 +76,8 @@ bus_driver_send_service_owner_changed (const char *service_name, DBUS_TYPE_INVALID)) goto oom; + _dbus_assert (dbus_message_has_signature (message, "sss")); + retval = bus_dispatch_matches (transaction, NULL, NULL, message, error); dbus_message_unref (message); @@ -346,6 +349,8 @@ bus_driver_send_welcome_message (DBusConnection *connection, return FALSE; } + _dbus_assert (dbus_message_has_signature (welcome, "s")); + if (!bus_transaction_send_from_driver (transaction, connection, welcome)) { dbus_message_unref (welcome); diff --git a/bus/test.c b/bus/test.c index 4071fb18..90d044ec 100644 --- a/bus/test.c +++ b/bus/test.c @@ -231,10 +231,12 @@ bus_test_client_listed (DBusConnection *connection) void bus_test_run_clients_loop (dbus_bool_t block_once) -{ +{ if (client_loop == NULL) return; + _dbus_verbose ("---> Dispatching on \"client side\"\n"); + /* dispatch before we block so pending dispatches * won't make our block return early */ @@ -250,12 +252,16 @@ bus_test_run_clients_loop (dbus_bool_t block_once) /* Then mop everything up */ while (_dbus_loop_iterate (client_loop, FALSE)) ; + + _dbus_verbose ("---> Done dispatching on \"client side\"\n"); } void bus_test_run_bus_loop (BusContext *context, dbus_bool_t block_once) { + _dbus_verbose ("---> Dispatching on \"server side\"\n"); + /* dispatch before we block so pending dispatches * won't make our block return early */ @@ -271,6 +277,8 @@ bus_test_run_bus_loop (BusContext *context, /* Then mop everything up */ while (_dbus_loop_iterate (bus_context_get_loop (context), FALSE)) ; + + _dbus_verbose ("---> Done dispatching on \"server side\"\n"); } void diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h index 38e54a94..b5781d9c 100644 --- a/dbus/dbus-connection-internal.h +++ b/dbus/dbus-connection-internal.h @@ -52,7 +52,7 @@ dbus_bool_t _dbus_connection_queue_received_message (DBusConnection DBusMessage *message); void _dbus_connection_queue_received_message_link (DBusConnection *connection, DBusList *link); -dbus_bool_t _dbus_connection_have_messages_to_send (DBusConnection *connection); +dbus_bool_t _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection); DBusMessage* _dbus_connection_get_message_to_send (DBusConnection *connection); void _dbus_connection_message_sent (DBusConnection *connection, DBusMessage *message); diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 6dcc2687..2f8b4c6f 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* dbus-connection.c DBusConnection object * - * Copyright (C) 2002, 2003 Red Hat Inc. + * Copyright (C) 2002, 2003, 2004 Red Hat Inc. * * Licensed under the Academic Free License version 2.1 * @@ -54,6 +54,12 @@ #define CONNECTION_UNLOCK(connection) dbus_mutex_unlock ((connection)->mutex) #endif +#define DISPATCH_STATUS_NAME(s) \ + ((s) == DBUS_DISPATCH_COMPLETE ? "complete" : \ + (s) == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : \ + (s) == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : \ + "???") + /** * @defgroup DBusConnection DBusConnection * @ingroup DBus @@ -350,12 +356,15 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection, _dbus_connection_wakeup_mainloop (connection); - _dbus_verbose ("Message %p (%d %s '%s') added to incoming queue %p, %d incoming\n", + _dbus_verbose ("Message %p (%d %s %s '%s') added to incoming queue %p, %d incoming\n", message, dbus_message_get_type (message), dbus_message_get_interface (message) ? dbus_message_get_interface (message) : "no interface", + dbus_message_get_member (message) ? + dbus_message_get_member (message) : + "no member", dbus_message_get_signature (message), connection, connection->n_incoming); @@ -388,16 +397,37 @@ _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, /** * Checks whether there are messages in the outgoing message queue. + * Called with connection lock held. * * @param connection the connection. * @returns #TRUE if the outgoing queue is non-empty. */ dbus_bool_t -_dbus_connection_have_messages_to_send (DBusConnection *connection) +_dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection) { return connection->outgoing_messages != NULL; } +/** + * Checks whether there are messages in the outgoing message queue. + * + * @param connection the connection. + * @returns #TRUE if the outgoing queue is non-empty. + */ +dbus_bool_t +dbus_connection_has_messages_to_send (DBusConnection *connection) +{ + dbus_bool_t v; + + _dbus_return_val_if_fail (connection != NULL, FALSE); + + CONNECTION_LOCK (connection); + v = _dbus_connection_has_messages_to_send_unlocked (connection); + CONNECTION_UNLOCK (connection); + + return v; +} + /** * Gets the next outgoing message. The message remains in the * queue, and the caller does not own a reference to it. @@ -424,8 +454,11 @@ _dbus_connection_message_sent (DBusConnection *connection, DBusMessage *message) { DBusList *link; - - _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); + + /* This can be called before we even complete authentication, since + * it's called on disconnect to clean up the outgoing queue. + * It's also called as we successfully send each message. + */ link = _dbus_list_get_last_link (&connection->outgoing_messages); _dbus_assert (link != NULL); @@ -438,12 +471,15 @@ _dbus_connection_message_sent (DBusConnection *connection, connection->n_outgoing -= 1; - _dbus_verbose ("Message %p (%d %s '%s') removed from outgoing queue %p, %d left to send\n", + _dbus_verbose ("Message %p (%d %s %s '%s') removed from outgoing queue %p, %d left to send\n", message, dbus_message_get_type (message), dbus_message_get_interface (message) ? dbus_message_get_interface (message) : "no interface", + dbus_message_get_member (message) ? + dbus_message_get_member (message) : + "no member", dbus_message_get_signature (message), connection, connection->n_outgoing); @@ -453,10 +489,6 @@ _dbus_connection_message_sent (DBusConnection *connection, _dbus_list_prepend_link (&connection->link_cache, link); dbus_message_unref (message); - - if (connection->n_outgoing == 0) - _dbus_transport_messages_pending (connection->transport, - connection->n_outgoing); } /** @@ -501,6 +533,7 @@ _dbus_connection_remove_watch (DBusConnection *connection, * Toggles a watch and notifies app via connection's * DBusWatchToggledFunction if available. It's an error to call this * function on a watch that was not previously added. + * Connection lock should be held when calling this. * * @param connection the connection. * @param watch the watch to toggle. @@ -511,6 +544,8 @@ _dbus_connection_toggle_watch (DBusConnection *connection, DBusWatch *watch, dbus_bool_t enabled) { + _dbus_assert (watch != NULL); + if (connection->watches) /* null during finalize */ _dbus_watch_list_toggle_watch (connection->watches, watch, enabled); @@ -777,6 +812,8 @@ _dbus_connection_release_io_path (DBusConnection *connection) * wasn't specified, then it's impossible to block, even if * you specify DBUS_ITERATION_BLOCK; in that case the function * returns immediately. + * + * Called with connection lock held. * * @param connection the connection. * @param flags iteration flags. @@ -1001,11 +1038,11 @@ _dbus_connection_unref_unlocked (DBusConnection *connection) #ifdef DBUS_HAVE_ATOMIC_INT last_unref = (_dbus_atomic_dec (&connection->refcount) == 1); -#else +#else _dbus_assert (connection->refcount.value > 0); connection->refcount.value -= 1; - last_unref = (connection->refcount.value == 0); + last_unref = (connection->refcount.value == 0); #if 0 printf ("unref_unlocked() connection %p count = %d\n", connection, connection->refcount.value); #endif @@ -1311,6 +1348,8 @@ dbus_connection_disconnect (DBusConnection *connection) DBusDispatchStatus status; _dbus_return_if_fail (connection != NULL); + + _dbus_verbose ("Disconnecting %p\n", connection); CONNECTION_LOCK (connection); _dbus_transport_disconnect (connection->transport); @@ -1504,6 +1543,7 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection *connection, dbus_uint32_t *client_serial) { dbus_uint32_t serial; + const char *sig; preallocated->queue_link->data = message; _dbus_list_prepend_link (&connection->outgoing_messages, @@ -1519,13 +1559,27 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection *connection, connection->n_outgoing += 1; - _dbus_verbose ("Message %p (%d %s '%s') added to outgoing queue %p, %d pending to send\n", + sig = dbus_message_get_signature (message); +#ifndef DBUS_DISABLE_ASSERT + { + DBusString foo; + _dbus_verbose (" validating signature '%s'\n", sig); + _dbus_string_init_const (&foo, sig); + _dbus_assert (_dbus_string_validate_signature (&foo, 0, + _dbus_string_get_length (&foo))); + } +#endif + + _dbus_verbose ("Message %p (%d %s %s '%s') added to outgoing queue %p, %d pending to send\n", message, dbus_message_get_type (message), dbus_message_get_interface (message) ? dbus_message_get_interface (message) : "no interface", - dbus_message_get_signature (message), + dbus_message_get_member (message) ? + dbus_message_get_member (message) : + "no member", + sig, connection, connection->n_outgoing); @@ -1544,11 +1598,16 @@ _dbus_connection_send_preallocated_unlocked (DBusConnection *connection, _dbus_message_lock (message); - if (connection->n_outgoing == 1) - _dbus_transport_messages_pending (connection->transport, - connection->n_outgoing); + /* Now we need to run an iteration to hopefully just write the messages + * out immediately, and otherwise get them queued up + */ + _dbus_connection_do_iteration (connection, + DBUS_ITERATION_DO_WRITING, + -1); - _dbus_connection_wakeup_mainloop (connection); + /* If stuff is still queued up, be sure we wake up the main loop */ + if (connection->n_outgoing > 0) + _dbus_connection_wakeup_mainloop (connection); } /** @@ -2195,12 +2254,15 @@ _dbus_connection_pop_message_link_unlocked (DBusConnection *connection) link = _dbus_list_pop_first_link (&connection->incoming_messages); connection->n_incoming -= 1; - _dbus_verbose ("Message %p (%d %s '%s') removed from incoming queue %p, %d incoming\n", + _dbus_verbose ("Message %p (%d %s %s '%s') removed from incoming queue %p, %d incoming\n", link->data, dbus_message_get_type (link->data), dbus_message_get_interface (link->data) ? dbus_message_get_interface (link->data) : "no interface", + dbus_message_get_member (link->data) ? + dbus_message_get_member (link->data) : + "no member", dbus_message_get_signature (link->data), connection, connection->n_incoming); @@ -2246,12 +2308,15 @@ _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, message_link); connection->n_incoming += 1; - _dbus_verbose ("Message %p (%d %s '%s') put back into queue %p, %d incoming\n", + _dbus_verbose ("Message %p (%d %s %s '%s') put back into queue %p, %d incoming\n", message_link->data, dbus_message_get_type (message_link->data), dbus_message_get_interface (message_link->data) ? dbus_message_get_interface (message_link->data) : "no interface", + dbus_message_get_member (message_link->data) ? + dbus_message_get_member (message_link->data) : + "no member", dbus_message_get_signature (message_link->data), connection, connection->n_incoming); } @@ -2347,19 +2412,46 @@ _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) else { DBusDispatchStatus status; + dbus_bool_t is_connected; status = _dbus_transport_get_dispatch_status (connection->transport); + is_connected = _dbus_transport_get_is_connected (connection->transport); - if (status == DBUS_DISPATCH_COMPLETE && - connection->disconnect_message_link && - !_dbus_transport_get_is_connected (connection->transport)) + _dbus_verbose ("dispatch status = %s is_connected = %d\n", + DISPATCH_STATUS_NAME (status), is_connected); + + if (!is_connected) { - /* We haven't sent the disconnect message already, - * and all real messages have been queued up. + if (status == DBUS_DISPATCH_COMPLETE && + connection->disconnect_message_link) + { + _dbus_verbose ("Sending disconnect message from %s\n", + _DBUS_FUNCTION_NAME); + + /* We haven't sent the disconnect message already, + * and all real messages have been queued up. + */ + _dbus_connection_queue_synthesized_message_link (connection, + connection->disconnect_message_link); + connection->disconnect_message_link = NULL; + } + + /* Dump the outgoing queue, we aren't going to be able to + * send it now, and we'd like accessors like + * dbus_connection_get_outgoing_size() to be accurate. */ - _dbus_connection_queue_synthesized_message_link (connection, - connection->disconnect_message_link); - connection->disconnect_message_link = NULL; + if (connection->n_outgoing > 0) + { + DBusList *link; + + _dbus_verbose ("Dropping %d outgoing messages since we're disconnected\n", + connection->n_outgoing); + + while ((link = _dbus_list_get_last_link (&connection->outgoing_messages))) + { + _dbus_connection_message_sent (connection, link->data); + } + } } if (status != DBUS_DISPATCH_COMPLETE) @@ -2397,10 +2489,7 @@ _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connectio { _dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n", connection, new_status, - new_status == DBUS_DISPATCH_COMPLETE ? "complete" : - new_status == DBUS_DISPATCH_DATA_REMAINS ? "data remains" : - new_status == DBUS_DISPATCH_NEED_MEMORY ? "need memory" : - "???"); + DISPATCH_STATUS_NAME (new_status)); (* function) (connection, new_status, data); } @@ -2470,6 +2559,8 @@ dbus_connection_dispatch (DBusConnection *connection) _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); + _dbus_verbose ("%s\n", _DBUS_FUNCTION_NAME); + CONNECTION_LOCK (connection); status = _dbus_connection_get_dispatch_status_unlocked (connection); if (status != DBUS_DISPATCH_DATA_REMAINS) @@ -2497,6 +2588,8 @@ dbus_connection_dispatch (DBusConnection *connection) { /* another thread dispatched our stuff */ + _dbus_verbose ("another thread dispatched message\n"); + _dbus_connection_release_dispatch (connection); status = _dbus_connection_get_dispatch_status_unlocked (connection); @@ -2509,6 +2602,17 @@ dbus_connection_dispatch (DBusConnection *connection) } message = message_link->data; + + _dbus_verbose (" dispatching message %p (%d %s %s '%s')\n", + message, + dbus_message_get_type (message), + dbus_message_get_interface (message) ? + dbus_message_get_interface (message) : + "no interface", + dbus_message_get_member (message) ? + dbus_message_get_member (message) : + "no member", + dbus_message_get_signature (message)); result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -2563,7 +2667,10 @@ dbus_connection_dispatch (DBusConnection *connection) CONNECTION_LOCK (connection); if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) - goto out; + { + _dbus_verbose ("No memory in %s\n", _DBUS_FUNCTION_NAME); + goto out; + } /* Did a reply we were waiting on get filtered? */ if (pending && result == DBUS_HANDLER_RESULT_HANDLED) @@ -2583,7 +2690,10 @@ dbus_connection_dispatch (DBusConnection *connection) } if (result == DBUS_HANDLER_RESULT_HANDLED) - goto out; + { + _dbus_verbose ("filter handled message in dispatch\n"); + goto out; + } if (pending) { @@ -2592,18 +2702,22 @@ dbus_connection_dispatch (DBusConnection *connection) pending = NULL; CONNECTION_LOCK (connection); + _dbus_verbose ("pending call completed in dispatch\n"); goto out; } /* We're still protected from dispatch() reentrancy here * since we acquired the dispatcher */ - _dbus_verbose (" running object path dispatch on message %p (%d %s '%s')\n", + _dbus_verbose (" running object path dispatch on message %p (%d %s %s '%s')\n", message, dbus_message_get_type (message), dbus_message_get_interface (message) ? dbus_message_get_interface (message) : "no interface", + dbus_message_get_member (message) ? + dbus_message_get_member (message) : + "no member", dbus_message_get_signature (message)); result = _dbus_object_tree_dispatch_and_unlock (connection->objects, @@ -2612,7 +2726,10 @@ dbus_connection_dispatch (DBusConnection *connection) CONNECTION_LOCK (connection); if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) - goto out; + { + _dbus_verbose ("object tree handled message in dispatch\n"); + goto out; + } if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) { @@ -2626,6 +2743,7 @@ dbus_connection_dispatch (DBusConnection *connection) if (!_dbus_string_init (&str)) { result = DBUS_HANDLER_RESULT_NEED_MEMORY; + _dbus_verbose ("no memory for error string in dispatch\n"); goto out; } @@ -2636,6 +2754,7 @@ dbus_connection_dispatch (DBusConnection *connection) { _dbus_string_free (&str); result = DBUS_HANDLER_RESULT_NEED_MEMORY; + _dbus_verbose ("no memory for error string in dispatch\n"); goto out; } @@ -2647,6 +2766,7 @@ dbus_connection_dispatch (DBusConnection *connection) if (reply == NULL) { result = DBUS_HANDLER_RESULT_NEED_MEMORY; + _dbus_verbose ("no memory for error reply in dispatch\n"); goto out; } @@ -2656,6 +2776,7 @@ dbus_connection_dispatch (DBusConnection *connection) { dbus_message_unref (reply); result = DBUS_HANDLER_RESULT_NEED_MEMORY; + _dbus_verbose ("no memory for error send in dispatch\n"); goto out; } @@ -2667,11 +2788,14 @@ dbus_connection_dispatch (DBusConnection *connection) result = DBUS_HANDLER_RESULT_HANDLED; } - _dbus_verbose (" done dispatching %p (%d %s '%s') on connection %p\n", message, + _dbus_verbose (" done dispatching %p (%d %s %s '%s') on connection %p\n", message, dbus_message_get_type (message), dbus_message_get_interface (message) ? dbus_message_get_interface (message) : "no interface", + dbus_message_get_member (message) ? + dbus_message_get_member (message) : + "no member", dbus_message_get_signature (message), connection); @@ -2689,7 +2813,7 @@ dbus_connection_dispatch (DBusConnection *connection) } else { - _dbus_verbose ("Done with message in %s\n", _DBUS_FUNCTION_NAME); + _dbus_verbose (" ... done dispatching in %s\n", _DBUS_FUNCTION_NAME); if (connection->exit_on_disconnect && dbus_message_is_signal (message, diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index 79606ecf..a74ba410 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -105,6 +105,7 @@ void dbus_connection_steal_borrowed_message (DBusConnection DBusMessage* dbus_connection_pop_message (DBusConnection *connection); DBusDispatchStatus dbus_connection_get_dispatch_status (DBusConnection *connection); DBusDispatchStatus dbus_connection_dispatch (DBusConnection *connection); +dbus_bool_t dbus_connection_has_messages_to_send (DBusConnection *connection); dbus_bool_t dbus_connection_send (DBusConnection *connection, DBusMessage *message, dbus_uint32_t *client_serial); diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c index e390e4d5..6d2395fd 100644 --- a/dbus/dbus-internals.c +++ b/dbus/dbus-internals.c @@ -191,6 +191,7 @@ _dbus_verbose_real (const char *format, va_list args; static dbus_bool_t verbose = TRUE; static dbus_bool_t need_pid = TRUE; + int len; /* things are written a bit oddly here so that * in the non-verbose case we just have the one @@ -207,18 +208,16 @@ _dbus_verbose_real (const char *format, return; } + /* Print out pid before the line */ if (need_pid) - { - int len; - - fprintf (stderr, "%lu: ", _dbus_getpid ()); - - len = strlen (format); - if (format[len-1] == '\n') - need_pid = TRUE; - else - need_pid = FALSE; - } + fprintf (stderr, "%lu: ", _dbus_getpid ()); + + /* Only print pid again if the next line is a new line */ + len = strlen (format); + if (format[len-1] == '\n') + need_pid = TRUE; + else + need_pid = FALSE; va_start (args, format); vfprintf (stderr, format, args); @@ -418,6 +417,8 @@ _dbus_header_field_to_string (int header_field) return "destination"; case DBUS_HEADER_FIELD_SENDER: return "sender"; + case DBUS_HEADER_FIELD_SIGNATURE: + return "signature"; default: return "unknown"; } diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c index 9877dca6..615a145d 100644 --- a/dbus/dbus-keyring.c +++ b/dbus/dbus-keyring.c @@ -759,7 +759,7 @@ _dbus_keyring_new_homedir (const DBusString *username, { _dbus_string_set_length (&homedir, 0); if (!_dbus_string_append (&homedir, override)) - _dbus_assert_not_reached ("no memory"); + goto failed; _dbus_verbose ("Using fake homedir for testing: %s\n", _dbus_string_get_const_data (&homedir)); diff --git a/dbus/dbus-mainloop.c b/dbus/dbus-mainloop.c index 886ff049..99369d48 100644 --- a/dbus/dbus-mainloop.c +++ b/dbus/dbus-mainloop.c @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* dbus-mainloop.c Main loop utility * - * Copyright (C) 2003 Red Hat, Inc. + * Copyright (C) 2003, 2004 Red Hat, Inc. * * Licensed under the Academic Free License version 2.1 * @@ -30,6 +30,27 @@ #define MAINLOOP_SPEW 0 +#ifdef MAINLOOP_SPEW +#ifdef DBUS_ENABLE_VERBOSE_MODE +static const char* +watch_flags_to_string (int flags) +{ + const char *watch_type; + + if ((flags & DBUS_WATCH_READABLE) && + (flags & DBUS_WATCH_WRITABLE)) + watch_type = "readwrite"; + else if (flags & DBUS_WATCH_READABLE) + watch_type = "read"; + else if (flags & DBUS_WATCH_WRITABLE) + watch_type = "write"; + else + watch_type = "not read or write"; + return watch_type; +} +#endif /* DBUS_ENABLE_VERBOSE_MODE */ +#endif /* MAINLOOP_SPEW */ + struct DBusLoop { int refcount; @@ -597,7 +618,8 @@ _dbus_loop_iterate (DBusLoop *loop, fds[n_fds].events |= _DBUS_POLLOUT; #if MAINLOOP_SPEW - _dbus_verbose (" polling watch on fd %d\n", fds[n_fds].fd); + _dbus_verbose (" polling watch on fd %d %s\n", + fds[n_fds].fd, watch_flags_to_string (flags)); #endif n_fds += 1; @@ -605,8 +627,9 @@ _dbus_loop_iterate (DBusLoop *loop, else { #if MAINLOOP_SPEW - _dbus_verbose (" skipping disabled watch on fd %d\n", - dbus_watch_get_fd (wcb->watch)); + _dbus_verbose (" skipping disabled watch on fd %d %s\n", + dbus_watch_get_fd (wcb->watch), + watch_flags_to_string (dbus_watch_get_flags (wcb->watch))); #endif } } diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 0b3b1bf2..3b3ae1e9 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -525,8 +525,10 @@ iterate_one_field (const DBusString *str, int value_end; int pos; +#if 0 _dbus_verbose ("%s: name_offset=%d, append to %p\n", _DBUS_FUNCTION_NAME, name_offset, append_copy_to); +#endif pos = name_offset; @@ -547,9 +549,12 @@ iterate_one_field (const DBusString *str, array_type = _dbus_string_get_byte (str, pos); } - _dbus_verbose ("%s: name %d, type '%c' %d at %d len %d, array type '%c' %d\n", +#if 0 + _dbus_verbose ("%s: name %s, type '%c' %d at %d len %d, array type '%c' %d\n", _DBUS_FUNCTION_NAME, - name, type, type, type_pos, type_len, array_type, array_type); + _dbus_header_field_to_string (name), + type, type, type_pos, type_len, array_type, array_type); +#endif #ifndef DBUS_DISABLE_ASSERT if (!_dbus_type_is_valid (array_type)) @@ -631,7 +636,7 @@ verify_header_fields (DBusMessage *message) { int i; i = 0; - while (i < DBUS_HEADER_FIELD_LAST) + while (i <= DBUS_HEADER_FIELD_LAST) { if (message->header_fields[i].name_offset >= 0) _dbus_assert (_dbus_string_get_byte (&message->header, @@ -656,7 +661,7 @@ delete_one_and_re_align (DBusMessage *message, int next_offset; int field_name; dbus_bool_t retval; - HeaderField new_header_fields[DBUS_HEADER_FIELD_LAST]; + HeaderField new_header_fields[DBUS_HEADER_FIELD_LAST+1]; _dbus_assert (name_offset_to_delete < _dbus_string_get_length (&message->header)); verify_header_fields (message); @@ -703,7 +708,11 @@ delete_one_and_re_align (DBusMessage *message, &field_name, NULL, NULL, NULL)) _dbus_assert_not_reached ("shouldn't have failed to alloc memory to skip the deleted field"); - if (field_name < DBUS_HEADER_FIELD_LAST) + _dbus_verbose (" Skipping %s field which will be deleted; next_offset = %d\n", + _dbus_header_field_to_string (field_name), next_offset); + + /* This field no longer exists */ + if (field_name <= DBUS_HEADER_FIELD_LAST) { new_header_fields[field_name].name_offset = -1; new_header_fields[field_name].value_offset = -1; @@ -728,10 +737,16 @@ delete_one_and_re_align (DBusMessage *message, goto out_1; } - if (field_name < DBUS_HEADER_FIELD_LAST) + if (field_name <= DBUS_HEADER_FIELD_LAST) { new_header_fields[field_name].name_offset = copy_name_offset - new_fields_front_padding + name_offset_to_delete; new_header_fields[field_name].value_offset = copy_value_offset - new_fields_front_padding + name_offset_to_delete; + + _dbus_verbose (" Re-adding %s field at name_offset = %d value_offset = %d; next_offset = %d\n", + _dbus_header_field_to_string (field_name), + new_header_fields[field_name].name_offset, + new_header_fields[field_name].value_offset, + next_offset); } } @@ -801,6 +816,9 @@ set_int_field (DBusMessage *message, int offset = message->header_fields[field].value_offset; _dbus_assert (!message->locked); + + _dbus_verbose ("set_int_field() field %d value '%d'\n", + field, value); if (offset < 0) { @@ -826,6 +844,9 @@ set_uint_field (DBusMessage *message, int offset = message->header_fields[field].value_offset; _dbus_assert (!message->locked); + + _dbus_verbose ("set_uint_field() field %d value '%u'\n", + field, value); if (offset < 0) { @@ -860,8 +881,8 @@ set_string_field (DBusMessage *message, */ prealloc = value_len + MAX_BYTES_OVERHEAD_TO_APPEND_A_STRING; - _dbus_verbose ("set_string_field() field %d prealloc %d\n", - field, prealloc); + _dbus_verbose ("set_string_field() field %d prealloc %d value '%s'\n", + field, prealloc, value); if (!delete_field (message, field, prealloc)) return FALSE; @@ -5118,8 +5139,6 @@ decode_header_data (const DBusString *data, &field_data, pos, type)) return FALSE; -#if 0 - /* FIXME */ if (!_dbus_string_validate_signature (&field_data, 0, _dbus_string_get_length (&field_data))) { @@ -5127,7 +5146,6 @@ decode_header_data (const DBusString *data, _dbus_string_get_const_data (&field_data)); return FALSE; } -#endif break; default: @@ -7316,6 +7334,77 @@ _dbus_message_test (const char *test_data_dir) } dbus_free (t); + dbus_message_unref (message); + + /* This ServiceAcquired message used to trigger a bug in + * setting header fields, adding to regression test. + */ + message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "ServiceAcquired"); + + if (message == NULL) + _dbus_assert_not_reached ("out of memory"); + + _dbus_verbose ("Bytes after creation\n"); + _dbus_verbose_bytes_of_string (&message->header, 0, + _dbus_string_get_length (&message->header)); + + if (!dbus_message_set_destination (message, ":1.0") || + !dbus_message_append_args (message, + DBUS_TYPE_STRING, ":1.0", + DBUS_TYPE_INVALID)) + _dbus_assert_not_reached ("out of memory"); + + _dbus_verbose ("Bytes after set_destination() and append_args()\n"); + _dbus_verbose_bytes_of_string (&message->header, 0, + _dbus_string_get_length (&message->header)); + + if (!dbus_message_set_sender (message, "org.freedesktop.DBus")) + _dbus_assert_not_reached ("out of memory"); + + _dbus_verbose ("Bytes after set_sender()\n"); + _dbus_verbose_bytes_of_string (&message->header, 0, + _dbus_string_get_length (&message->header)); + + /* When the bug happened the above set_destination() would + * corrupt the signature + */ + if (!dbus_message_has_signature (message, "s")) + { + _dbus_warn ("Signature should be 's' but is '%s'\n", + dbus_message_get_signature (message)); + _dbus_assert_not_reached ("signal has wrong signature"); + } + + /* have to set destination again to reproduce the bug */ + if (!dbus_message_set_destination (message, ":1.0")) + _dbus_assert_not_reached ("out of memory"); + + _dbus_verbose ("Bytes after set_destination()\n"); + _dbus_verbose_bytes_of_string (&message->header, 0, + _dbus_string_get_length (&message->header)); + + /* When the bug happened the above set_destination() would + * corrupt the signature + */ + if (!dbus_message_has_signature (message, "s")) + { + _dbus_warn ("Signature should be 's' but is '%s'\n", + dbus_message_get_signature (message)); + _dbus_assert_not_reached ("signal has wrong signature"); + } + + dbus_error_init (&error); + if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, + &t, DBUS_TYPE_INVALID)) + + { + _dbus_warn ("Failed to get expected string arg for signal: %s\n", error.message); + exit (1); + } + dbus_free (t); + dbus_message_unref (message); /* Now load every message in test_data_dir if we have one */ diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 6e0e0f49..12f4ca6a 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -58,11 +58,10 @@ static void unix_finalize (DBusServer *server) { DBusServerUnix *unix_server = (DBusServerUnix*) server; - - dbus_free (unix_server->socket_name); _dbus_server_finalize_base (server); - + + dbus_free (unix_server->socket_name); dbus_free (server); } diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index 1611ff02..87969912 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* dbus-string.c String utility class (internal to D-BUS implementation) * - * Copyright (C) 2002, 2003 Red Hat, Inc. + * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. * * Licensed under the Academic Free License version 2.1 * @@ -2362,7 +2362,7 @@ _dbus_string_hex_decode (const DBusString *source, * string, returns #FALSE. * * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that isn't in the string. + * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check @@ -2406,7 +2406,7 @@ _dbus_string_validate_ascii (const DBusString *str, * boundaries, returns #FALSE. * * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that isn't in the string. + * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check @@ -2504,7 +2504,7 @@ _dbus_string_validate_utf8 (const DBusString *str, * #FALSE. * * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that isn't in the string. + * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check @@ -2545,7 +2545,7 @@ _dbus_string_validate_nul (const DBusString *str, * to be done separately for now. * * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that isn't in the string. + * it allows a start,len range that extends past the string end. * * @todo change spec to disallow more things, such as spaces in the * path name @@ -2631,7 +2631,7 @@ _dbus_string_validate_path (const DBusString *str, * ASCII subset, see the specification. * * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that isn't in the string. + * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check @@ -2708,7 +2708,7 @@ _dbus_string_validate_interface (const DBusString *str, * see the specification. * * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that isn't in the string. + * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check @@ -2770,7 +2770,7 @@ _dbus_string_validate_member (const DBusString *str, * see the specification. * * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that isn't in the string. + * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check @@ -2841,7 +2841,7 @@ _dbus_string_validate_base_service (const DBusString *str, * see the specification. * * @todo this is inconsistent with most of DBusString in that - * it allows a start,len range that isn't in the string. + * it allows a start,len range that extends past the string end. * * @param str the string * @param start first byte index to check @@ -2861,6 +2861,64 @@ _dbus_string_validate_service (const DBusString *str, return _dbus_string_validate_interface (str, start, len); } +/** + * Checks that the given range of the string is a valid message type + * signature in the D-BUS protocol. + * + * @todo this is inconsistent with most of DBusString in that + * it allows a start,len range that extends past the string end. + * + * @param str the string + * @param start first byte index to check + * @param len number of bytes to check + * @returns #TRUE if the byte range exists and is a valid signature + */ +dbus_bool_t +_dbus_string_validate_signature (const DBusString *str, + int start, + int len) +{ + const unsigned char *s; + const unsigned char *end; + DBUS_CONST_STRING_PREAMBLE (str); + _dbus_assert (start >= 0); + _dbus_assert (start <= real->len); + _dbus_assert (len >= 0); + + if (len > real->len - start) + return FALSE; + + s = real->str + start; + end = s + len; + while (s != end) + { + switch (*s) + { + case DBUS_TYPE_NIL: + case DBUS_TYPE_BYTE: + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: + case DBUS_TYPE_INT64: + case DBUS_TYPE_UINT64: + case DBUS_TYPE_DOUBLE: + case DBUS_TYPE_STRING: + case DBUS_TYPE_CUSTOM: + case DBUS_TYPE_ARRAY: + case DBUS_TYPE_DICT: + case DBUS_TYPE_OBJECT_PATH: + break; + + default: + return FALSE; + } + + ++s; + } + + return TRUE; +} + /** * Clears all allocated bytes in the string to zero. * @@ -3227,6 +3285,21 @@ _dbus_string_test (void) " ", "foo bar" }; + + const char *valid_signatures[] = { + "", + "sss", + "i", + "b" + }; + + const char *invalid_signatures[] = { + " ", + "not a valid signature", + "123", + ".", + "(" + }; i = 0; while (i < _DBUS_N_ELEMENTS (lens)) @@ -3811,6 +3884,37 @@ _dbus_string_test (void) ++i; } + /* Signature validation */ + i = 0; + while (i < (int) _DBUS_N_ELEMENTS (valid_signatures)) + { + _dbus_string_init_const (&str, valid_signatures[i]); + + if (!_dbus_string_validate_signature (&str, 0, + _dbus_string_get_length (&str))) + { + _dbus_warn ("Signature \"%s\" should have been valid\n", valid_signatures[i]); + _dbus_assert_not_reached ("invalid signature"); + } + + ++i; + } + + i = 0; + while (i < (int) _DBUS_N_ELEMENTS (invalid_signatures)) + { + _dbus_string_init_const (&str, invalid_signatures[i]); + + if (_dbus_string_validate_signature (&str, 0, + _dbus_string_get_length (&str))) + { + _dbus_warn ("Signature \"%s\" should have been invalid\n", invalid_signatures[i]); + _dbus_assert_not_reached ("valid signature"); + } + + ++i; + } + /* Validate claimed length longer than real length */ _dbus_string_init_const (&str, "abc.efg"); if (_dbus_string_validate_service (&str, 0, 8)) @@ -3824,6 +3928,10 @@ _dbus_string_test (void) if (_dbus_string_validate_member (&str, 0, 4)) _dbus_assert_not_reached ("validated too-long string"); + _dbus_string_init_const (&str, "sss"); + if (_dbus_string_validate_signature (&str, 0, 4)) + _dbus_assert_not_reached ("validated too-long signature"); + /* Validate string exceeding max name length */ if (!_dbus_string_init (&str)) _dbus_assert_not_reached ("no memory"); diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h index cf526e43..51f41a4c 100644 --- a/dbus/dbus-string.h +++ b/dbus/dbus-string.h @@ -253,6 +253,9 @@ dbus_bool_t _dbus_string_validate_error_name (const DBusString *str, dbus_bool_t _dbus_string_validate_service (const DBusString *str, int start, int len); +dbus_bool_t _dbus_string_validate_signature (const DBusString *str, + int start, + int len); void _dbus_string_zero (DBusString *str); diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 2bdd8171..8c3a2be4 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -3019,6 +3019,9 @@ _dbus_full_duplex_pipe (int *fd1, *fd1 = fds[0]; *fd2 = fds[1]; + + _dbus_verbose ("full-duplex pipe %d <-> %d\n", + *fd1, *fd2); return TRUE; #else diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 275326db..54195933 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* dbus-transport-protected.h Used by subclasses of DBusTransport object (internal to D-BUS implementation) * - * Copyright (C) 2002 Red Hat Inc. + * Copyright (C) 2002, 2004 Red Hat Inc. * * Licensed under the Academic Free License version 2.1 * @@ -56,12 +56,6 @@ struct DBusTransportVTable dbus_bool_t (* connection_set) (DBusTransport *transport); /**< Called when transport->connection has been filled in */ - void (* messages_pending) (DBusTransport *transport, - int queue_length); - /**< Called when the outgoing message queue goes from empty - * to non-empty or vice versa. - */ - void (* do_iteration) (DBusTransport *transport, unsigned int flags, int timeout_milliseconds); @@ -111,7 +105,6 @@ struct DBusTransport unsigned int disconnected : 1; /**< #TRUE if we are disconnected. */ unsigned int authenticated : 1; /**< Cache of auth state; use _dbus_transport_get_is_authenticated() to query value */ - unsigned int messages_need_sending : 1; /**< #TRUE if we need to write messages out */ unsigned int send_credentials_pending : 1; /**< #TRUE if we need to send credentials */ unsigned int receive_credentials_pending : 1; /**< #TRUE if we need to receive credentials */ unsigned int is_server : 1; /**< #TRUE if on the server side */ diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index f7a49af2..a33b8f78 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -1,7 +1,7 @@ /* -*- mode: C; c-file-style: "gnu" -*- */ /* dbus-transport-unix.c UNIX socket subclasses of DBusTransport * - * Copyright (C) 2002, 2003 Red Hat Inc. + * Copyright (C) 2002, 2003, 2004 Red Hat Inc. * * Licensed under the Academic Free License version 2.1 * @@ -114,7 +114,7 @@ static void check_write_watch (DBusTransport *transport) { DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; - dbus_bool_t need_write_watch; + dbus_bool_t needed; if (transport->connection == NULL) return; @@ -128,14 +128,37 @@ check_write_watch (DBusTransport *transport) _dbus_transport_ref (transport); if (_dbus_transport_get_is_authenticated (transport)) - need_write_watch = transport->messages_need_sending; + needed = _dbus_connection_has_messages_to_send_unlocked (transport->connection); else - need_write_watch = transport->send_credentials_pending || - _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND; + { + if (transport->send_credentials_pending) + needed = TRUE; + else + { + DBusAuthState auth_state; + + auth_state = _dbus_auth_do_work (transport->auth); + + /* If we need memory we install the write watch just in case, + * if there's no need for it, it will get de-installed + * next time we try reading. + */ + if (auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND || + auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY) + needed = TRUE; + else + needed = FALSE; + } + } + + _dbus_verbose ("check_write_watch(): needed = %d on connection %p watch %p fd = %d outgoing messages exist %d\n", + needed, transport->connection, unix_transport->write_watch, + unix_transport->fd, + _dbus_connection_has_messages_to_send_unlocked (transport->connection)); _dbus_connection_toggle_watch (transport->connection, unix_transport->write_watch, - need_write_watch); + needed); _dbus_transport_unref (transport); } @@ -146,6 +169,9 @@ check_read_watch (DBusTransport *transport) DBusTransportUnix *unix_transport = (DBusTransportUnix*) transport; dbus_bool_t need_read_watch; + _dbus_verbose ("%s: fd = %d\n", + _DBUS_FUNCTION_NAME, unix_transport->fd); + if (transport->connection == NULL) return; @@ -161,9 +187,35 @@ check_read_watch (DBusTransport *transport) need_read_watch = _dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size; else - need_read_watch = transport->receive_credentials_pending || - _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_WAITING_FOR_INPUT; + { + if (transport->receive_credentials_pending) + need_read_watch = TRUE; + else + { + /* The reason to disable need_read_watch when not WAITING_FOR_INPUT + * is to avoid spinning on the file descriptor when we're waiting + * to write or for some other part of the auth process + */ + DBusAuthState auth_state; + + auth_state = _dbus_auth_do_work (transport->auth); + + /* If we need memory we install the read watch just in case, + * if there's no need for it, it will get de-installed + * next time we try reading. If we're authenticated we + * install it since we normally have it installed while + * authenticated. + */ + if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT || + auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY || + auth_state == DBUS_AUTH_STATE_AUTHENTICATED) + need_read_watch = TRUE; + else + need_read_watch = FALSE; + } + } + _dbus_verbose (" setting read watch enabled = %d\n", need_read_watch); _dbus_connection_toggle_watch (transport->connection, unix_transport->read_watch, need_read_watch); @@ -326,12 +378,24 @@ do_authentication (DBusTransport *transport, { dbus_bool_t oom; dbus_bool_t orig_auth_state; - - _dbus_transport_ref (transport); oom = FALSE; orig_auth_state = _dbus_transport_get_is_authenticated (transport); + + /* This is essential to avoid the check_write_watch() at the end, + * we don't want to add a write watch in do_iteration before + * we try writing and get EAGAIN + */ + if (orig_auth_state) + { + if (auth_completed) + *auth_completed = FALSE; + return TRUE; + } + + _dbus_transport_ref (transport); + while (!_dbus_transport_get_is_authenticated (transport) && _dbus_transport_get_is_connected (transport)) { @@ -418,16 +482,17 @@ do_writing (DBusTransport *transport) return TRUE; } -#if 0 - _dbus_verbose ("do_writing(), have_messages = %d\n", - _dbus_connection_have_messages_to_send (transport->connection)); +#if 1 + _dbus_verbose ("do_writing(), have_messages = %d, fd = %d\n", + _dbus_connection_has_messages_to_send_unlocked (transport->connection), + unix_transport->fd); #endif oom = FALSE; total = 0; while (!transport->disconnected && - _dbus_connection_have_messages_to_send (transport->connection)) + _dbus_connection_has_messages_to_send_unlocked (transport->connection)) { int bytes_written; DBusMessage *message; @@ -442,12 +507,6 @@ do_writing (DBusTransport *transport) total, unix_transport->max_bytes_written_per_iteration); goto out; } - - if (!dbus_watch_get_enabled (unix_transport->write_watch)) - { - _dbus_verbose ("write watch disabled, not writing more stuff\n"); - goto out; - } message = _dbus_connection_get_message_to_send (transport->connection); _dbus_assert (message != NULL); @@ -580,6 +639,9 @@ do_reading (DBusTransport *transport) int total; dbus_bool_t oom; + _dbus_verbose ("%s: fd = %d\n", _DBUS_FUNCTION_NAME, + unix_transport->fd); + /* No messages without authentication! */ if (!_dbus_transport_get_is_authenticated (transport)) return TRUE; @@ -722,6 +784,7 @@ unix_handle_watch (DBusTransport *transport, _dbus_assert (watch == unix_transport->read_watch || watch == unix_transport->write_watch); + _dbus_assert (watch != NULL); /* Disconnect in case of an error. In case of hangup do not * disconnect the transport because data can still be in the buffer @@ -741,8 +804,9 @@ unix_handle_watch (DBusTransport *transport, (flags & DBUS_WATCH_READABLE)) { dbus_bool_t auth_finished; -#if 0 - _dbus_verbose ("handling read watch (%x)\n", flags); +#if 1 + _dbus_verbose ("handling read watch %p flags = %x\n", + watch, flags); #endif if (!do_authentication (transport, TRUE, FALSE, &auth_finished)) return FALSE; @@ -761,13 +825,17 @@ unix_handle_watch (DBusTransport *transport, return FALSE; } } + else + { + _dbus_verbose ("Not reading anything since we just completed the authentication\n"); + } } else if (watch == unix_transport->write_watch && (flags & DBUS_WATCH_WRITABLE)) { -#if 0 - _dbus_verbose ("handling write watch, messages_need_sending = %d\n", - transport->messages_need_sending); +#if 1 + _dbus_verbose ("handling write watch, have_outgoing_messages = %d\n", + _dbus_connection_has_messages_to_send_unlocked (transport->connection)); #endif if (!do_authentication (transport, FALSE, TRUE, NULL)) return FALSE; @@ -777,6 +845,9 @@ unix_handle_watch (DBusTransport *transport, _dbus_verbose ("no memory to write\n"); return FALSE; } + + /* See if we still need the write watch */ + check_write_watch (transport); } #ifdef DBUS_ENABLE_VERBOSE_MODE else @@ -838,13 +909,6 @@ unix_connection_set (DBusTransport *transport) return TRUE; } -static void -unix_messages_pending (DBusTransport *transport, - int messages_pending) -{ - check_write_watch (transport); -} - /** * @todo We need to have a way to wake up the select sleep if * a new iteration request comes in with a flag (read/write) that @@ -862,20 +926,18 @@ unix_do_iteration (DBusTransport *transport, int poll_res; int poll_timeout; - _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p\n", + _dbus_verbose (" iteration flags = %s%s timeout = %d read_watch = %p write_watch = %p fd = %d\n", flags & DBUS_ITERATION_DO_READING ? "read" : "", flags & DBUS_ITERATION_DO_WRITING ? "write" : "", timeout_milliseconds, unix_transport->read_watch, - unix_transport->write_watch); + unix_transport->write_watch, + unix_transport->fd); /* the passed in DO_READING/DO_WRITING flags indicate whether to * read/write messages, but regardless of those we may need to block * for reading/writing to do auth. But if we do reading for auth, * we don't want to read any messages yet if not given DO_READING. - * - * Also, if read_watch == NULL or write_watch == NULL, we don't - * want to read/write so don't. */ poll_fd.fd = unix_transport->fd; @@ -883,12 +945,12 @@ unix_do_iteration (DBusTransport *transport, if (_dbus_transport_get_is_authenticated (transport)) { - if (unix_transport->read_watch && - (flags & DBUS_ITERATION_DO_READING)) + _dbus_assert (unix_transport->read_watch); + if (flags & DBUS_ITERATION_DO_READING) poll_fd.events |= _DBUS_POLLIN; - - if (unix_transport->write_watch && - (flags & DBUS_ITERATION_DO_WRITING)) + + _dbus_assert (unix_transport->write_watch); + if (flags & DBUS_ITERATION_DO_WRITING) poll_fd.events |= _DBUS_POLLOUT; } else @@ -904,7 +966,7 @@ unix_do_iteration (DBusTransport *transport, if (transport->send_credentials_pending || auth_state == DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND) poll_fd.events |= _DBUS_POLLOUT; - } + } if (poll_fd.events) { @@ -947,7 +1009,7 @@ unix_do_iteration (DBusTransport *transport, /* See comment in unix_handle_watch. */ if (authentication_completed) - return; + goto out; if (need_read && (flags & DBUS_ITERATION_DO_READING)) do_reading (transport); @@ -961,6 +1023,22 @@ unix_do_iteration (DBusTransport *transport, _dbus_strerror (errno)); } } + + + out: + /* We need to install the write watch only if we did not + * successfully write everything. Note we need to be careful that we + * don't call check_write_watch *before* do_writing, since it's + * inefficient to add the write watch, and we can avoid it most of + * the time since we can write immediately. + * + * However, we MUST always call check_write_watch(); DBusConnection code + * relies on the fact that running an iteration will notice that + * messages are pending. + */ + check_write_watch (transport); + + _dbus_verbose (" ... leaving do_iteration()\n"); } static void @@ -987,7 +1065,6 @@ static DBusTransportVTable unix_vtable = { unix_handle_watch, unix_disconnect, unix_connection_set, - unix_messages_pending, unix_do_iteration, unix_live_messages_changed, unix_get_unix_fd diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index da487cc7..1a9da4a3 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -141,7 +141,6 @@ _dbus_transport_init_base (DBusTransport *transport, transport->auth = auth; transport->live_messages_size = counter; transport->authenticated = FALSE; - transport->messages_need_sending = FALSE; transport->disconnected = FALSE; transport->send_credentials_pending = !server; transport->receive_credentials_pending = server; @@ -610,32 +609,6 @@ _dbus_transport_set_connection (DBusTransport *transport, return transport->connection != NULL; } -/** - * Notifies the transport when the outgoing message queue goes from - * empty to non-empty or vice versa. Typically causes the transport to - * add or remove its DBUS_WATCH_WRITABLE watch. - * - * @param transport the transport. - * @param queue_length the length of the outgoing message queue. - * - */ -void -_dbus_transport_messages_pending (DBusTransport *transport, - int queue_length) -{ - _dbus_assert (transport->vtable->messages_pending != NULL); - - if (transport->disconnected) - return; - - transport->messages_need_sending = queue_length > 0; - - _dbus_transport_ref (transport); - (* transport->vtable->messages_pending) (transport, - queue_length); - _dbus_transport_unref (transport); -} - /** * Get the UNIX file descriptor, if any. * diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 20d53b7d..8359474d 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -44,8 +44,6 @@ dbus_bool_t _dbus_transport_handle_watch (DBusTransport unsigned int condition); dbus_bool_t _dbus_transport_set_connection (DBusTransport *transport, DBusConnection *connection); -void _dbus_transport_messages_pending (DBusTransport *transport, - int queue_length); void _dbus_transport_do_iteration (DBusTransport *transport, unsigned int flags, int timeout_milliseconds); diff --git a/dbus/dbus-watch.c b/dbus/dbus-watch.c index 02bfbb83..dbc0fb48 100644 --- a/dbus/dbus-watch.c +++ b/dbus/dbus-watch.c @@ -268,8 +268,27 @@ _dbus_watch_list_set_functions (DBusWatchList *watch_list, DBusList *next = _dbus_list_get_next_link (&watch_list->watches, link); - _dbus_verbose ("Adding a watch on fd %d using newly-set add watch function\n", - dbus_watch_get_fd (link->data)); +#ifdef DBUS_ENABLE_VERBOSE_MODE + { + const char *watch_type; + int flags; + + flags = dbus_watch_get_flags (link->data); + if ((flags & DBUS_WATCH_READABLE) && + (flags & DBUS_WATCH_WRITABLE)) + watch_type = "readwrite"; + else if (flags & DBUS_WATCH_READABLE) + watch_type = "read"; + else if (flags & DBUS_WATCH_WRITABLE) + watch_type = "write"; + else + watch_type = "not read or write"; + + _dbus_verbose ("Adding a %s watch on fd %d using newly-set add watch function\n", + watch_type, + dbus_watch_get_fd (link->data)); + } +#endif /* DBUS_ENABLE_VERBOSE_MODE */ if (!(* add_function) (link->data, data)) { @@ -402,8 +421,8 @@ _dbus_watch_list_toggle_watch (DBusWatchList *watch_list, if (watch_list->watch_toggled_function != NULL) { - _dbus_verbose ("Toggling watch on fd %d to %d\n", - dbus_watch_get_fd (watch), watch->enabled); + _dbus_verbose ("Toggling watch %p on fd %d to %d\n", + watch, dbus_watch_get_fd (watch), watch->enabled); (* watch_list->watch_toggled_function) (watch, watch_list->watch_data); diff --git a/doc/TODO b/doc/TODO index 11374a98..1158262f 100644 --- a/doc/TODO +++ b/doc/TODO @@ -90,6 +90,9 @@ Might as Well for 1.0 - dbus_message_iter_init_array_iterator has "iter" and "iterator" in the same function name + - connection_open/connection_disconnect lacks symmetry, open/close + or connect/disconnect + Can Be Post 1.0 === diff --git a/test/glib/test-profile.c b/test/glib/test-profile.c index 2b7cb5b8..64fa6377 100644 --- a/test/glib/test-profile.c +++ b/test/glib/test-profile.c @@ -689,7 +689,7 @@ static const ProfileRunVTable plain_sockets_vtable = { plain_sockets_main_loop_run }; -static void +static double do_profile_run (const ProfileRunVTable *vtable) { GTimer *timer; @@ -726,6 +726,8 @@ do_profile_run (const ProfileRunVTable *vtable) (* vtable->stop_server) (&sd, server); g_main_loop_unref (sd.loop); + + return secs; } int @@ -744,10 +746,18 @@ main (int argc, char *argv[]) if (argc > 1 && strcmp (argv[1], "plain_sockets") == 0) do_profile_run (&plain_sockets_vtable); + if (argc > 1 && strcmp (argv[1], "both") == 0) + { + double e1, e2; + + e1 = do_profile_run (&plain_sockets_vtable); + e2 = do_profile_run (&with_bus_vtable); + + g_printerr ("libdbus version is %g times slower than plain sockets\n", + e2/e1); + } else do_profile_run (&with_bus_vtable); return 0; } - - -- cgit v1.2.1