2004-11-25 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Fri, 26 Nov 2004 01:53:13 +0000 (01:53 +0000)
committerHavoc Pennington <hp@redhat.com>
Fri, 26 Nov 2004 01:53:13 +0000 (01:53 +0000)
        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.

22 files changed:
ChangeLog
bus/dispatch.c
bus/driver.c
bus/test.c
dbus/dbus-connection-internal.h
dbus/dbus-connection.c
dbus/dbus-connection.h
dbus/dbus-internals.c
dbus/dbus-keyring.c
dbus/dbus-mainloop.c
dbus/dbus-message.c
dbus/dbus-server-unix.c
dbus/dbus-string.c
dbus/dbus-string.h
dbus/dbus-sysdeps.c
dbus/dbus-transport-protected.h
dbus/dbus-transport-unix.c
dbus/dbus-transport.c
dbus/dbus-transport.h
dbus/dbus-watch.c
doc/TODO
test/glib/test-profile.c

index f85dd6b..c9f42f4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index 3cd1c3e..e04d289 100644 (file)
@@ -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");
 
index b426912..dc64039 100644 (file)
@@ -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);
index 4071fb1..90d044e 100644 (file)
@@ -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
index 38e54a9..b5781d9 100644 (file)
@@ -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);
index 6dcc268..2f8b4c6 100644 (file)
@@ -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
  * 
 #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,
index 79606ec..a74ba41 100644 (file)
@@ -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);
index e390e4d..6d2395f 100644 (file)
@@ -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";
     }
index 9877dca..615a145 100644 (file)
@@ -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));
index 886ff04..99369d4 100644 (file)
@@ -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
  * 
 
 #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
             }
         }
index 0b3b1bf..3b3ae1e 100644 (file)
@@ -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)
index 6e0e0f4..12f4ca6 100644 (file)
@@ -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);
 }
 
index 1611ff0..8796991 100644 (file)
@@ -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");
index cf526e4..51f41a4 100644 (file)
@@ -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);
 
 
index 2bdd817..8c3a2be 100644 (file)
@@ -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
index 275326d..5419593 100644 (file)
@@ -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 */
index f7a49af..a33b8f7 100644 (file)
@@ -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
index da487cc..1a9da4a 100644 (file)
@@ -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
index 20d53b7..8359474 100644 (file)
@@ -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);
index 02bfbb8..dbc0fb4 100644 (file)
@@ -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);
index 11374a9..1158262 100644 (file)
--- 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
 ===
 
index 2b7cb5b..64fa637 100644 (file)
@@ -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;
 }
-
-