diff options
| -rw-r--r-- | ChangeLog | 63 | ||||
| -rw-r--r-- | bus/dispatch.c | 139 | ||||
| -rw-r--r-- | bus/driver.c | 9 | ||||
| -rw-r--r-- | bus/test.c | 10 | ||||
| -rw-r--r-- | dbus/dbus-connection-internal.h | 2 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 200 | ||||
| -rw-r--r-- | dbus/dbus-connection.h | 1 | ||||
| -rw-r--r-- | dbus/dbus-internals.c | 23 | ||||
| -rw-r--r-- | dbus/dbus-keyring.c | 2 | ||||
| -rw-r--r-- | dbus/dbus-mainloop.c | 31 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 111 | ||||
| -rw-r--r-- | dbus/dbus-server-unix.c | 5 | ||||
| -rw-r--r-- | dbus/dbus-string.c | 126 | ||||
| -rw-r--r-- | dbus/dbus-string.h | 3 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.c | 3 | ||||
| -rw-r--r-- | dbus/dbus-transport-protected.h | 9 | ||||
| -rw-r--r-- | dbus/dbus-transport-unix.c | 167 | ||||
| -rw-r--r-- | dbus/dbus-transport.c | 27 | ||||
| -rw-r--r-- | dbus/dbus-transport.h | 2 | ||||
| -rw-r--r-- | dbus/dbus-watch.c | 27 | ||||
| -rw-r--r-- | doc/TODO | 3 | ||||
| -rw-r--r-- | test/glib/test-profile.c | 16 | 
22 files changed, 772 insertions, 207 deletions
| @@ -1,3 +1,66 @@ +2004-11-25  Havoc Pennington  <hp@redhat.com> + +        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  <hp@redhat.com>  	* 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 <stdio.h> +/* 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); @@ -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,17 +397,38 @@ _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: @@ -7317,6 +7335,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 */    if (test_data_dir == NULL) 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 @@ -2862,6 +2862,64 @@ _dbus_string_validate_service (const DBusString  *str,  }  /** + * 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.   *   * @param str the string @@ -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; @@ -611,32 +610,6 @@ _dbus_transport_set_connection (DBusTransport  *transport,  }  /** - * 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.   *   * @param transport the transport 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); @@ -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;  } - -   | 
