summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-03-15 06:00:01 +0000
committerHavoc Pennington <hp@redhat.com>2003-03-15 06:00:01 +0000
commitf05f87a825ab8ed5273674a7f65521ffc526f0d2 (patch)
treea4645e057d269b6bc7d2d99e89ba7606625b3686
parent169238e99a4a163c89eb053250daeedf5f73e5cd (diff)
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.
-rw-r--r--ChangeLog18
-rw-r--r--bus/connection.c2
-rw-r--r--bus/dispatch.c153
-rw-r--r--bus/test.c87
-rw-r--r--bus/utils.c6
-rw-r--r--configure.in2
-rw-r--r--dbus/Makefile.am2
-rw-r--r--dbus/dbus-memory.c6
-rw-r--r--dbus/dbus-mempool.c5
-rw-r--r--dbus/dbus-message.c8
-rw-r--r--dbus/dbus-sysdeps.c34
-rw-r--r--dbus/dbus-sysdeps.h2
-rw-r--r--dbus/dbus-transport-unix.c16
13 files changed, 312 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index 09ae8f17..5c477ee7 100644
--- 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
diff --git a/bus/connection.c b/bus/connection.c
index 700ca46d..1c699c6f 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -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);
diff --git a/bus/dispatch.c b/bus/dispatch.c
index 35ea5549..ac2fb15b 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -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;
}
diff --git a/bus/test.c b/bus/test.c
index 3b933388..8d8aa492 100644
--- a/bus/test.c
+++ b/bus/test.c
@@ -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
diff --git a/bus/utils.c b/bus/utils.c
index 8b964cc4..fadfc140 100644
--- a/bus/utils.c
+++ b/bus/utils.c
@@ -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
}
diff --git a/configure.in b/configure.in
index 2d442478..78db7baf 100644
--- a/configure.in
+++ b/configure.in
@@ -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([
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index e9b08d13..c66c5367 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -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 \
diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c
index 83d17e6c..e1075228 100644
--- a/dbus/dbus-memory.c
+++ b/dbus/dbus-memory.c
@@ -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;
}
diff --git a/dbus/dbus-mempool.c b/dbus/dbus-mempool.c
index 2fde2568..9a0f6188 100644
--- a/dbus/dbus-mempool.c
+++ b/dbus/dbus-mempool.c
@@ -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)
{
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index b1fc6483..fe032dff 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -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)
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 7117e8fb..e6e0b276 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -50,6 +50,10 @@
#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 */
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index 8cd62207..0c24d0c5 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -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 */
diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c
index dfaeb1ad..3c5fe848 100644
--- a/dbus/dbus-transport-unix.c
+++ b/dbus/dbus-transport-unix.c
@@ -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);
}