diff options
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | bus/connection.c | 2 | ||||
-rw-r--r-- | bus/dispatch.c | 153 | ||||
-rw-r--r-- | bus/test.c | 87 | ||||
-rw-r--r-- | bus/utils.c | 6 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | dbus/Makefile.am | 2 | ||||
-rw-r--r-- | dbus/dbus-memory.c | 6 | ||||
-rw-r--r-- | dbus/dbus-mempool.c | 5 | ||||
-rw-r--r-- | dbus/dbus-message.c | 8 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.c | 34 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 2 | ||||
-rw-r--r-- | dbus/dbus-transport-unix.c | 16 |
13 files changed, 312 insertions, 29 deletions
@@ -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; } @@ -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); } |