2003-03-15 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Sat, 15 Mar 2003 06:00:01 +0000 (06:00 +0000)
committerHavoc Pennington <hp@redhat.com>
Sat, 15 Mar 2003 06:00:01 +0000 (06:00 +0000)
* bus/dispatch.c (bus_dispatch_test): OK, now finally actually
write useful test code, after all that futzing around ;-)

Test does not yet pass because we can't handle OOM in
_dbus_transport_messages_pending (basically,
dbus_connection_preallocate_send() does not prealloc the write
watch). To fix this, I think we need to add new stuff to
set_watch_functions, namely a SetEnabled function so we can alloc
the watch earlier, then enable it later.

* dbus/Makefile.am (libdbus_convenience_la_SOURCES): move
dbus-memory.c to the convenience lib

* bus/test.c: rename some static functions to keep them clearly
distinct from stuff in connection.c. Handle client disconnection.

13 files changed:
ChangeLog
bus/connection.c
bus/dispatch.c
bus/test.c
bus/utils.c
configure.in
dbus/Makefile.am
dbus/dbus-memory.c
dbus/dbus-mempool.c
dbus/dbus-message.c
dbus/dbus-sysdeps.c
dbus/dbus-sysdeps.h
dbus/dbus-transport-unix.c

index 09ae8f1..5c477ee 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2003-03-15  Havoc Pennington  <hp@pobox.com>
+
+       * bus/dispatch.c (bus_dispatch_test): OK, now finally actually
+       write useful test code, after all that futzing around ;-)
+
+       Test does not yet pass because we can't handle OOM in
+       _dbus_transport_messages_pending (basically,
+       dbus_connection_preallocate_send() does not prealloc the write
+       watch). To fix this, I think we need to add new stuff to
+       set_watch_functions, namely a SetEnabled function so we can alloc
+       the watch earlier, then enable it later.
+       
+       * dbus/Makefile.am (libdbus_convenience_la_SOURCES): move
+       dbus-memory.c to the convenience lib
+
+       * bus/test.c: rename some static functions to keep them clearly 
+       distinct from stuff in connection.c. Handle client disconnection.
+
 2003-03-14  Havoc Pennington  <hp@pobox.com>
 
        * bus/dispatch.c (bus_dispatch_test): do test using debug-pipe 
index 700ca46..1c699c6 100644 (file)
@@ -56,8 +56,6 @@ bus_connection_disconnected (DBusConnection *connection)
 {
   BusConnectionData *d;
   BusService *service;
-  
-  _dbus_warn ("Disconnected\n");
 
   d = BUS_CONNECTION_DATA (connection);
   _dbus_assert (d != NULL);  
index 35ea554..ac2fb15 100644 (file)
@@ -377,6 +377,10 @@ bus_dispatch_remove_connection (DBusConnection *connection)
 
 #ifdef DBUS_BUILD_TESTS
 
+typedef dbus_bool_t (* Check1Func) (BusContext     *context);
+typedef dbus_bool_t (* Check2Func) (BusContext     *context,
+                                    DBusConnection *connection);
+
 static void
 flush_bus (BusContext *context)
 {  
@@ -384,6 +388,15 @@ flush_bus (BusContext *context)
     ;
 }
 
+static void
+kill_client_connection (DBusConnection *connection)
+{
+  /* kick in the disconnect handler that unrefs the connection */
+  dbus_connection_disconnect (connection);
+  while (dbus_connection_dispatch_message (connection))
+    ;
+}
+
 /* returns TRUE if the correct thing happens,
  * but the correct thing may include OOM errors.
  */
@@ -393,6 +406,10 @@ check_hello_message (BusContext     *context,
 {
   DBusMessage *message;
   dbus_int32_t serial;
+  dbus_bool_t retval;
+  DBusError error;
+
+  dbus_error_init (&error);
   
   message = dbus_message_new (DBUS_SERVICE_DBUS,
                              DBUS_MESSAGE_HELLO);
@@ -404,25 +421,150 @@ check_hello_message (BusContext     *context,
     return TRUE;
 
   dbus_message_unref (message);
+  message = NULL;
   
   flush_bus (context);
 
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      return TRUE;
+    }
+  
+  retval = FALSE;
+  
   message = dbus_connection_pop_message (connection);
   if (message == NULL)
     {
       _dbus_warn ("Did not receive a reply to %s %d on %p\n",
                   DBUS_MESSAGE_HELLO, serial, connection);
-      return FALSE;
+      goto out;
     }
 
   _dbus_verbose ("Received %s on %p\n",
                  dbus_message_get_name (message), connection);
+
+  if (dbus_message_get_is_error (message))
+    {
+      if (dbus_message_name_is (message,
+                                DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else
+        {
+          _dbus_warn ("Did not expect error %s\n",
+                      dbus_message_get_name (message));
+          goto out;
+        }
+    }
+  else
+    {
+      char *str;
+      
+      if (dbus_message_name_is (message,
+                                DBUS_MESSAGE_HELLO))
+        {
+          ; /* good, expected */
+        }
+      else
+        {
+          _dbus_warn ("Did not expect reply %s\n",
+                      dbus_message_get_name (message));
+          goto out;
+        }
+
+      if (!dbus_message_get_args (message, &error,
+                                  DBUS_TYPE_STRING, &str,
+                                  DBUS_TYPE_INVALID))
+        {
+          _dbus_warn ("Did not get the expected single string argument\n");
+          goto out;
+        }
+
+      _dbus_verbose ("Got hello name: %s\n", str);
+      dbus_free (str);
+    }
+      
+  retval = TRUE;
   
-  dbus_message_unref (message);
+ out:
+  if (message)
+    dbus_message_unref (message);
   
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_hello_connection (BusContext *context)
+{
+  DBusConnection *connection;
+  DBusResultCode result;
+
+  result = DBUS_RESULT_SUCCESS;
+  connection = dbus_connection_open ("debug-pipe:name=test-server", &result);
+  if (connection == NULL)
+    {
+      _dbus_assert (result != DBUS_RESULT_SUCCESS);
+      return TRUE;
+    }
+
+  if (!bus_setup_debug_client (connection))
+    {
+      dbus_connection_unref (connection);
+      return TRUE;
+    }
+
+  if (!check_hello_message (context, connection))
+    return FALSE;
+
+  kill_client_connection (connection);
+
   return TRUE;
 }
 
+static void
+check1_try_iterations (BusContext *context,
+                       const char *description,
+                       Check1Func  func)
+{
+  int approx_mallocs;
+
+  /* Run once to see about how many mallocs are involved */
+  
+  _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
+  
+  if (! (*func) (context))
+    _dbus_assert_not_reached ("test failed");
+
+  approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
+
+  _dbus_verbose ("=================\n%s: about %d mallocs total\n=================\n",
+                 description, approx_mallocs);
+  
+  approx_mallocs += 10; /* fudge factor */
+  
+  /* Now run failing each malloc */
+  
+  while (approx_mallocs >= 0)
+    {
+      _dbus_set_fail_alloc_counter (approx_mallocs);
+
+      _dbus_verbose ("\n===\n %s: (will fail malloc %d)\n===\n",
+                     description, approx_mallocs);
+
+      if (! (*func) (context))
+        _dbus_assert_not_reached ("test failed");
+
+      approx_mallocs -= 1;
+    }
+
+  _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
+}
+
 dbus_bool_t
 bus_dispatch_test (const DBusString *test_data_dir)
 {
@@ -440,6 +582,9 @@ bus_dispatch_test (const DBusString *test_data_dir)
                              &error);
   if (context == NULL)
     _dbus_assert_not_reached ("could not alloc context");
+
+  check1_try_iterations (context, "create_and_hello",
+                         check_hello_connection);
   
   foo = dbus_connection_open ("debug-pipe:name=test-server", &result);
   if (foo == NULL)
@@ -464,6 +609,10 @@ bus_dispatch_test (const DBusString *test_data_dir)
     _dbus_assert_not_reached ("hello message failed");
   if (!check_hello_message (context, baz))
     _dbus_assert_not_reached ("hello message failed");
+
+  dbus_connection_unref (foo);
+  dbus_connection_unref (bar);
+  dbus_connection_unref (baz);
   
   return TRUE;
 }
index 3b93338..8d8aa49 100644 (file)
@@ -26,6 +26,7 @@
 #ifdef DBUS_BUILD_TESTS
 #include "test.h"
 #include "loop.h"
+#include <dbus/dbus-internals.h>
 
 /* The "debug client" watch/timeout handlers don't dispatch messages,
  * as we manually pull them in order to verify them. This is why they
@@ -33,7 +34,7 @@
  */
 
 static void
-connection_watch_callback (DBusWatch     *watch,
+client_watch_callback (DBusWatch     *watch,
                            unsigned int   condition,
                            void          *data)
 {
@@ -47,22 +48,22 @@ connection_watch_callback (DBusWatch     *watch,
 }
 
 static dbus_bool_t
-add_connection_watch (DBusWatch      *watch,
+add_client_watch (DBusWatch      *watch,
                       DBusConnection *connection)
 {
-  return bus_loop_add_watch (watch, connection_watch_callback, connection,
+  return bus_loop_add_watch (watch, client_watch_callback, connection,
                              NULL);
 }
 
 static void
-remove_connection_watch (DBusWatch      *watch,
+remove_client_watch (DBusWatch      *watch,
                          DBusConnection *connection)
 {
-  bus_loop_remove_watch (watch, connection_watch_callback, connection);
+  bus_loop_remove_watch (watch, client_watch_callback, connection);
 }
 
 static void
-connection_timeout_callback (DBusTimeout   *timeout,
+client_timeout_callback (DBusTimeout   *timeout,
                              void          *data)
 {
   DBusConnection *connection = data;
@@ -75,43 +76,85 @@ connection_timeout_callback (DBusTimeout   *timeout,
 }
 
 static dbus_bool_t
-add_connection_timeout (DBusTimeout    *timeout,
+add_client_timeout (DBusTimeout    *timeout,
                         DBusConnection *connection)
 {
-  return bus_loop_add_timeout (timeout, connection_timeout_callback, connection, NULL);
+  return bus_loop_add_timeout (timeout, client_timeout_callback, connection, NULL);
 }
 
 static void
-remove_connection_timeout (DBusTimeout    *timeout,
+remove_client_timeout (DBusTimeout    *timeout,
                            DBusConnection *connection)
 {
-  bus_loop_remove_timeout (timeout, connection_timeout_callback, connection);
+  bus_loop_remove_timeout (timeout, client_timeout_callback, connection);
 }
 
+static DBusHandlerResult
+client_disconnect_handler (DBusMessageHandler *handler,
+                           DBusConnection     *connection,
+                           DBusMessage        *message,
+                           void               *user_data)
+{
+  dbus_connection_unref (connection);
+  
+  return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+}
 
 dbus_bool_t
 bus_setup_debug_client (DBusConnection *connection)
 {
+  DBusMessageHandler *disconnect_handler;
+  const char *to_handle[] = { DBUS_MESSAGE_LOCAL_DISCONNECT };
+  dbus_bool_t retval;
   
-  if (!dbus_connection_set_watch_functions (connection,
-                                            (DBusAddWatchFunction) add_connection_watch,
-                                            (DBusRemoveWatchFunction) remove_connection_watch,
-                                            connection,
-                                            NULL))
+  disconnect_handler = dbus_message_handler_new (client_disconnect_handler,
+                                                 NULL, NULL);
+
+  if (disconnect_handler == NULL)
+    return FALSE;
+
+  if (!dbus_connection_register_handler (connection,
+                                         disconnect_handler,
+                                         to_handle,
+                                         _DBUS_N_ELEMENTS (to_handle)))
     {
-      dbus_connection_disconnect (connection);
+      dbus_message_handler_unref (disconnect_handler);
       return FALSE;
     }
+
+  retval = FALSE;
   
+  if (!dbus_connection_set_watch_functions (connection,
+                                            (DBusAddWatchFunction) add_client_watch,
+                                            (DBusRemoveWatchFunction) remove_client_watch,
+                                            connection,
+                                            NULL))
+    goto out;
+      
   if (!dbus_connection_set_timeout_functions (connection,
-                                              (DBusAddTimeoutFunction) add_connection_timeout,
-                                              (DBusRemoveTimeoutFunction) remove_connection_timeout,
+                                              (DBusAddTimeoutFunction) add_client_timeout,
+                                              (DBusRemoveTimeoutFunction) remove_client_timeout,
                                               connection, NULL))
+    goto out;
+
+  retval = TRUE;
+  
+ out:
+  if (!retval)
     {
-      dbus_connection_disconnect (connection);
-      return FALSE;
+      dbus_connection_unregister_handler (connection,
+                                          disconnect_handler,
+                                          to_handle,
+                                          _DBUS_N_ELEMENTS (to_handle));
+      
+      dbus_connection_set_watch_functions (connection,
+                                           NULL, NULL, NULL, NULL);
+      dbus_connection_set_timeout_functions (connection,
+                                             NULL, NULL, NULL, NULL);
     }
-
-  return TRUE;
+  
+  dbus_message_handler_unref (disconnect_handler);
+  
+  return retval;
 }
 #endif
index 8b964cc..fadfc14 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <config.h>
 #include "utils.h"
 #include <dbus/dbus-sysdeps.h>
 
@@ -30,6 +31,11 @@ const char bus_no_memory_message[] = "Memory allocation failure in message bus";
 void
 bus_wait_for_memory (void)
 {
+#ifdef DBUS_BUILD_TESTS
+  /* make tests go fast */
+  _dbus_sleep_milliseconds (10);
+#else
   _dbus_sleep_milliseconds (500);
+#endif
 }
 
index 2d44247..78db7ba 100644 (file)
@@ -136,6 +136,8 @@ AC_CHECK_LIB(nsl,gethostbyname)
 
 AC_CHECK_FUNCS(vsnprintf vasprintf nanosleep usleep poll setenv socketpair)
 
+AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
+
 AC_CACHE_CHECK([for posix getpwnam_r],
                ac_cv_func_posix_getpwnam_r,
                [AC_TRY_RUN([
index e9b08d1..c66c536 100644 (file)
@@ -34,7 +34,6 @@ libdbus_1_la_SOURCES=                         \
        dbus-errors.c                           \
        dbus-keyring.c                          \
        dbus-keyring.h                          \
-       dbus-memory.c                           \
        dbus-message.c                          \
        dbus-message-handler.c                  \
        dbus-message-internal.h                 \
@@ -88,6 +87,7 @@ libdbus_convenience_la_SOURCES=                       \
        dbus-list.h                             \
        dbus-marshal.c                          \
        dbus-marshal.h                          \
+       dbus-memory.c                           \
        dbus-mempool.c                          \
        dbus-mempool.h                          \
        dbus-message-builder.c                  \
index 83d17e6..e107522 100644 (file)
@@ -256,6 +256,8 @@ dbus_malloc (size_t bytes)
     {
       if (fail_counts != -1)
        _dbus_set_fail_alloc_counter (fail_counts);
+
+      _dbus_verbose (" FAILING malloc of %d bytes\n", bytes);
       
       return NULL;
     }
@@ -297,6 +299,8 @@ dbus_malloc0 (size_t bytes)
     {
       if (fail_counts != -1)
        _dbus_set_fail_alloc_counter (fail_counts);
+
+      _dbus_verbose (" FAILING malloc0 of %d bytes\n", bytes);
       
       return NULL;
     }
@@ -340,6 +344,8 @@ dbus_realloc (void  *memory,
     {
       if (fail_counts != -1)
        _dbus_set_fail_alloc_counter (fail_counts);
+
+      _dbus_verbose (" FAILING realloc of %d bytes\n", bytes);
       
       return NULL;
     }
index 2fde256..9a0f618 100644 (file)
@@ -203,7 +203,10 @@ void*
 _dbus_mem_pool_alloc (DBusMemPool *pool)
 {
   if (_dbus_decrement_fail_alloc_counter ())
-    return NULL;
+    {
+      _dbus_verbose (" FAILING mempool alloc\n");
+      return NULL;
+    }
   
   if (pool->free_elements)
     {
index b1fc648..fe032df 100644 (file)
@@ -628,8 +628,10 @@ _dbus_message_add_size_counter (DBusMessage *message,
     _dbus_string_get_length (&message->header) +
     _dbus_string_get_length (&message->body);
 
+#if 0
   _dbus_verbose ("message has size %ld\n",
                  message->size_counter_delta);
+#endif
   
   _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
 }
@@ -2587,13 +2589,15 @@ decode_header_data (const DBusString   *data,
             }
           
           fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
+#if 0
           _dbus_verbose ("Found service name at offset %d\n",
                          fields[FIELD_SERVICE].offset);
+#endif
           break;
 
         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
           if (fields[FIELD_NAME].offset >= 0)
-            {
+            {              
               _dbus_verbose ("%s field provided twice\n",
                              DBUS_HEADER_FIELD_NAME);
               return FALSE;
@@ -2601,8 +2605,10 @@ decode_header_data (const DBusString   *data,
           
           fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
 
+#if 0
           _dbus_verbose ("Found message name at offset %d\n",
                          fields[FIELD_NAME].offset);
+#endif
           break;
        case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
           if (fields[FIELD_SENDER].offset >= 0)
index 7117e8f..e6e0b27 100644 (file)
 #ifdef HAVE_POLL
 #include <sys/poll.h>
 #endif
+#ifdef HAVE_BACKTRACE
+#include <execinfo.h>
+#endif
+
 
 #ifndef O_BINARY
 #define O_BINARY 0
@@ -2827,5 +2831,35 @@ _dbus_close (int        fd,
   return TRUE;
 }
 
+/**
+ * On GNU libc systems, print a crude backtrace to the verbose log.
+ * On other systems, print "no backtrace support"
+ *
+ */
+void
+_dbus_print_backtrace (void)
+{
+#if defined (HAVE_BACKTRACE) && defined (DBUS_ENABLE_VERBOSE_MODE)
+  void *bt[500];
+  int bt_size;
+  int i;
+  char **syms;
+  
+  bt_size = backtrace (bt, 500);
+
+  syms = backtrace_symbols (bt, bt_size);
+  
+  i = 0;
+  while (i < bt_size)
+    {
+      _dbus_verbose ("  %s\n", syms[i]);
+      ++i;
+    }
+
+  free (syms);
+#else
+  _dbus_verbose ("  D-BUS not compiled with backtrace support\n");
+#endif
+}
 
 /** @} end of sysdeps */
index 8cd6220..0c24d0c 100644 (file)
@@ -205,6 +205,8 @@ dbus_bool_t _dbus_full_duplex_pipe (int              *fd1,
 dbus_bool_t _dbus_close            (int               fd,
                                     DBusError        *error);
 
+void        _dbus_print_backtrace  (void);
+
 DBUS_END_DECLS;
 
 #endif /* DBUS_SYSDEPS_H */
index dfaeb1a..3c5fe84 100644 (file)
@@ -164,8 +164,10 @@ check_write_watch (DBusTransport *transport)
     }
   else
     {
+#if 0
       _dbus_verbose ("Write watch is unchanged from %p on fd %d\n",
                      unix_transport->write_watch, unix_transport->fd);
+#endif
     }
   
  out:
@@ -190,8 +192,10 @@ check_read_watch (DBusTransport *transport)
     need_read_watch = transport->receive_credentials_pending ||
       _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_WAITING_FOR_INPUT;
 
+#if 0
   _dbus_verbose ("need_read_watch = %d authenticated = %d\n",
                  need_read_watch, _dbus_transport_get_is_authenticated (transport));
+#endif
   
   if (transport->disconnected)
     need_read_watch = FALSE;
@@ -232,8 +236,10 @@ check_read_watch (DBusTransport *transport)
     }
   else
     {
+#if 0
       _dbus_verbose ("Read watch is unchanged from %p on fd %d\n",
                      unix_transport->read_watch, unix_transport->fd);
+#endif
     }
   
  out:
@@ -621,7 +627,9 @@ do_writing (DBusTransport *transport)
       _dbus_assert (message != NULL);
       _dbus_message_lock (message);
 
+#if 0
       _dbus_verbose ("writing message %p\n", message);
+#endif
       
       _dbus_message_get_network_data (message,
                                       &header, &body);
@@ -647,8 +655,10 @@ do_writing (DBusTransport *transport)
           
           total_bytes_to_write = _dbus_string_get_length (&unix_transport->encoded_message);
 
+#if 0
           _dbus_verbose ("encoded message is %d bytes\n",
                          total_bytes_to_write);
+#endif
           
           bytes_written =
             _dbus_write (unix_transport->fd,
@@ -660,8 +670,10 @@ do_writing (DBusTransport *transport)
         {
           total_bytes_to_write = header_len + body_len;
 
+#if 0
           _dbus_verbose ("message is %d bytes\n",
                          total_bytes_to_write);          
+#endif
           
           if (unix_transport->message_bytes_written < header_len)
             {
@@ -868,14 +880,18 @@ unix_handle_watch (DBusTransport *transport,
   if (watch == unix_transport->read_watch &&
       (flags & DBUS_WATCH_READABLE))
     {
+#if 0
       _dbus_verbose ("handling read watch\n");
+#endif
       do_authentication (transport, TRUE, FALSE);
       do_reading (transport);
     }
   else if (watch == unix_transport->write_watch &&
            (flags & DBUS_WATCH_WRITABLE))
     {
+#if 0
       _dbus_verbose ("handling write watch\n");
+#endif
       do_authentication (transport, FALSE, TRUE);
       do_writing (transport);
     }