diff options
Diffstat (limited to 'dbus')
-rw-r--r-- | dbus/dbus-connection.c | 29 | ||||
-rw-r--r-- | dbus/dbus-memory.c | 178 | ||||
-rw-r--r-- | dbus/dbus-message.c | 79 | ||||
-rw-r--r-- | dbus/dbus-message.h | 2 | ||||
-rw-r--r-- | dbus/dbus-server-debug.c | 28 | ||||
-rw-r--r-- | dbus/dbus-server.c | 6 | ||||
-rw-r--r-- | dbus/dbus-timeout.c | 5 | ||||
-rw-r--r-- | dbus/dbus-timeout.h | 1 | ||||
-rw-r--r-- | dbus/dbus-transport-debug.c | 259 | ||||
-rw-r--r-- | dbus/dbus-transport-unix.c | 7 |
10 files changed, 414 insertions, 180 deletions
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index d52341a7..c5df5611 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -207,8 +207,9 @@ _dbus_connection_queue_received_message (DBusConnection *connection, _dbus_connection_wakeup_mainloop (connection); _dbus_assert (dbus_message_get_name (message) != NULL); - _dbus_verbose ("Incoming message %p (%s) added to queue, %d incoming\n", + _dbus_verbose ("Message %p (%s) added to incoming queue %p, %d incoming\n", message, dbus_message_get_name (message), + connection, connection->n_incoming); return TRUE; @@ -234,8 +235,8 @@ _dbus_connection_queue_synthesized_message_link (DBusConnection *connection, _dbus_connection_wakeup_mainloop (connection); - _dbus_verbose ("Incoming synthesized message %p added to queue, %d incoming\n", - link->data, connection->n_incoming); + _dbus_verbose ("Synthesized message %p added to incoming queue %p, %d incoming\n", + link->data, connection, connection->n_incoming); } @@ -283,8 +284,8 @@ _dbus_connection_message_sent (DBusConnection *connection, connection->n_outgoing -= 1; - _dbus_verbose ("Message %p removed from outgoing queue, %d left to send\n", - message, connection->n_outgoing); + _dbus_verbose ("Message %p removed from outgoing queue %p, %d left to send\n", + message, connection, connection->n_outgoing); if (connection->n_outgoing == 0) _dbus_transport_messages_pending (connection->transport, @@ -334,7 +335,7 @@ _dbus_connection_remove_watch (DBusConnection *connection, * available. Otherwise records the timeout to be added when said * function is available. Also re-adds the timeout if the * DBusAddTimeoutFunction changes. May fail due to lack of memory. - * The timeout will fire only one time. + * The timeout will fire repeatedly until removed. * * @param connection the connection. * @param timeout the timeout to add. @@ -1035,9 +1036,10 @@ dbus_connection_send_preallocated (DBusConnection *connection, dbus_message_ref (message); connection->n_outgoing += 1; - _dbus_verbose ("Message %p (%s) added to outgoing queue, %d pending to send\n", + _dbus_verbose ("Message %p (%s) added to outgoing queue %p, %d pending to send\n", message, dbus_message_get_name (message), + connection, connection->n_outgoing); if (dbus_message_get_serial (message) == -1) @@ -1558,8 +1560,8 @@ _dbus_connection_pop_message_unlocked (DBusConnection *connection) message = _dbus_list_pop_first (&connection->incoming_messages); connection->n_incoming -= 1; - _dbus_verbose ("Incoming message %p removed from queue, %d incoming\n", - message, connection->n_incoming); + _dbus_verbose ("Message %p removed from incoming queue %p, %d incoming\n", + message, connection, connection->n_incoming); return message; } @@ -1859,11 +1861,10 @@ dbus_connection_set_watch_functions (DBusConnection *connection, * g_timeout_add. * * The DBusTimeout can be queried for the timer interval using - * dbus_timeout_get_interval. - * - * Once a timeout occurs, dbus_timeout_handle should be called to invoke - * the timeout's callback, and the timeout should be automatically - * removed. i.e. timeouts are one-shot. + * dbus_timeout_get_interval(). dbus_timeout_handle() should + * be called repeatedly, each time the interval elapses, starting + * after it has elapsed once. The timeout stops firing when + * it is removed with the given remove_function. * * @param connection the connection. * @param add_function function to add a timeout. diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c index 14ce23d8..5f0d9b8e 100644 --- a/dbus/dbus-memory.c +++ b/dbus/dbus-memory.c @@ -76,6 +76,13 @@ static dbus_bool_t inited = FALSE; static int fail_counts = -1; static size_t fail_size = 0; +static dbus_bool_t guards = FALSE; +#define GUARD_VALUE 0xdeadbeef +#define GUARD_INFO_SIZE 8 +#define GUARD_START_PAD 16 +#define GUARD_END_PAD 16 +#define GUARD_START_OFFSET (GUARD_START_PAD + GUARD_INFO_SIZE) +#define GUARD_EXTRA_SIZE (GUARD_START_OFFSET + GUARD_END_PAD) #endif #ifdef DBUS_BUILD_TESTS @@ -92,10 +99,133 @@ initialize_malloc_debug (void) if (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN") != NULL) fail_size = atoi (_dbus_getenv ("DBUS_MALLOC_FAIL_GREATER_THAN")); + + if (_dbus_getenv ("DBUS_MALLOC_GUARDS") != NULL) + guards = TRUE; inited = TRUE; } } + +typedef enum +{ + SOURCE_UNKNOWN, + SOURCE_MALLOC, + SOURCE_REALLOC, + SOURCE_MALLOC_ZERO, + SOURCE_REALLOC_NULL +} BlockSource; + +static const char* +source_string (BlockSource source) +{ + switch (source) + { + case SOURCE_UNKNOWN: + return "unknown"; + case SOURCE_MALLOC: + return "malloc"; + case SOURCE_REALLOC: + return "realloc"; + case SOURCE_MALLOC_ZERO: + return "malloc0"; + case SOURCE_REALLOC_NULL: + return "realloc(NULL)"; + } + _dbus_assert_not_reached ("Invalid malloc block source ID"); + return "invalid!"; +} + +static void +check_guards (void *free_block) +{ + if (free_block != NULL) + { + unsigned char *block = ((unsigned char*)free_block) - GUARD_START_OFFSET; + size_t requested_bytes = *(dbus_uint32_t*)block; + BlockSource source = *(dbus_uint32_t*)(block + 4); + unsigned int i; + dbus_bool_t failed; + + failed = FALSE; + +#if 0 + _dbus_verbose ("Checking %d bytes request from source %s\n", + requested_bytes, source_string (source)); +#endif + + i = GUARD_INFO_SIZE; + while (i < GUARD_START_OFFSET) + { + dbus_uint32_t value = *(dbus_uint32_t*) &block[i]; + if (value != GUARD_VALUE) + { + _dbus_warn ("Block of %u bytes from %s had start guard value 0x%x at %d expected 0x%x\n", + requested_bytes, source_string (source), + value, i, GUARD_VALUE); + failed = TRUE; + } + + i += 4; + } + + i = GUARD_START_OFFSET + requested_bytes; + while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD)) + { + dbus_uint32_t value = *(dbus_uint32_t*) &block[i]; + if (value != GUARD_VALUE) + { + _dbus_warn ("Block of %u bytes from %s had end guard value 0x%x at %d expected 0x%x\n", + requested_bytes, source_string (source), + value, i, GUARD_VALUE); + failed = TRUE; + } + + i += 4; + } + + if (failed) + _dbus_assert_not_reached ("guard value corruption"); + } +} + +static void* +set_guards (void *real_block, + size_t requested_bytes, + BlockSource source) +{ + unsigned char *block = real_block; + unsigned int i; + + if (block == NULL) + return NULL; + + _dbus_assert (GUARD_START_OFFSET + GUARD_END_PAD == GUARD_EXTRA_SIZE); + + *((dbus_uint32_t*)block) = requested_bytes; + *((dbus_uint32_t*)(block + 4)) = source; + + i = GUARD_INFO_SIZE; + while (i < GUARD_START_OFFSET) + { + (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE; + + i += 4; + } + + i = GUARD_START_OFFSET + requested_bytes; + while (i < (GUARD_START_OFFSET + requested_bytes + GUARD_END_PAD)) + { + (*(dbus_uint32_t*) &block[i]) = GUARD_VALUE; + + i += 4; + } + + check_guards (block + GUARD_START_OFFSET); + + return block + GUARD_START_OFFSET; +} + #endif /** @@ -127,6 +257,13 @@ dbus_malloc (size_t bytes) #if DBUS_BUILD_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; + else if (guards) + { + void *block; + + block = malloc (bytes + GUARD_EXTRA_SIZE); + return set_guards (block, bytes, SOURCE_MALLOC); + } #endif else return malloc (bytes); @@ -161,6 +298,13 @@ dbus_malloc0 (size_t bytes) #if DBUS_BUILD_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; + else if (guards) + { + void *block; + + block = calloc (bytes + GUARD_EXTRA_SIZE, 1); + return set_guards (block, bytes, SOURCE_MALLOC_ZERO); + } #endif else return calloc (bytes, 1); @@ -200,6 +344,30 @@ dbus_realloc (void *memory, #if DBUS_BUILD_TESTS else if (fail_size != 0 && bytes > fail_size) return NULL; + else if (guards) + { + if (memory) + { + void *block; + + check_guards (memory); + + block = realloc (((unsigned char*)memory) - GUARD_START_OFFSET, + bytes + GUARD_EXTRA_SIZE); + + /* old guards shouldn't have moved */ + check_guards (((unsigned char*)block) + GUARD_START_OFFSET); + + return set_guards (block, bytes, SOURCE_REALLOC); + } + else + { + void *block; + + block = malloc (bytes + GUARD_EXTRA_SIZE); + return set_guards (block, bytes, SOURCE_REALLOC_NULL); + } + } #endif else { @@ -216,6 +384,16 @@ dbus_realloc (void *memory, void dbus_free (void *memory) { +#ifdef DBUS_BUILD_TESTS + if (guards) + { + check_guards (memory); + if (memory) + free (((unsigned char*)memory) - GUARD_START_OFFSET); + return; + } +#endif + if (memory) /* we guarantee it's safe to free (NULL) */ free (memory); } diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 6a3c6618..b1fc6483 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -897,7 +897,7 @@ dbus_message_new_error_reply (DBusMessage *original_message, * @returns the new message. */ DBusMessage * -dbus_message_new_from_message (const DBusMessage *message) +dbus_message_copy (const DBusMessage *message) { DBusMessage *retval; int i; @@ -908,7 +908,11 @@ dbus_message_new_from_message (const DBusMessage *message) retval->refcount = 1; retval->byte_order = message->byte_order; - + retval->client_serial = message->client_serial; + retval->reply_serial = message->reply_serial; + retval->header_padding = message->header_padding; + retval->locked = FALSE; + if (!_dbus_string_init (&retval->header, _DBUS_INT_MAX)) { dbus_free (retval); @@ -3590,6 +3594,37 @@ dbus_internal_do_not_use_foreach_message_file (const char *test_d return retval; } +static void +verify_test_message (DBusMessage *message) +{ + dbus_int32_t our_int; + char *our_str; + double our_double; + dbus_bool_t our_bool; + + if (!dbus_message_get_args (message, NULL, + DBUS_TYPE_INT32, &our_int, + DBUS_TYPE_STRING, &our_str, + DBUS_TYPE_DOUBLE, &our_double, + DBUS_TYPE_BOOLEAN, &our_bool, + 0)) + _dbus_assert_not_reached ("Could not get arguments"); + + if (our_int != -0x12345678) + _dbus_assert_not_reached ("integers differ!"); + + if (our_double != 3.14159) + _dbus_assert_not_reached ("doubles differ!"); + + if (strcmp (our_str, "Test string") != 0) + _dbus_assert_not_reached ("strings differ!"); + + if (!our_bool) + _dbus_assert_not_reached ("booleans differ"); + + dbus_free (our_str); +} + /** * @ingroup DBusMessageInternals * Unit test for DBusMessage. @@ -3603,10 +3638,9 @@ _dbus_message_test (const char *test_data_dir) DBusMessageLoader *loader; int i; const char *data; - dbus_int32_t our_int; - char *our_str; - double our_double; - dbus_bool_t our_bool; + DBusMessage *copy; + const char *name1; + const char *name2; /* Test the vararg functions */ message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage"); @@ -3622,28 +3656,29 @@ _dbus_message_test (const char *test_data_dir) _dbus_verbose_bytes_of_string (&message->body, 0, _dbus_string_get_length (&message->body)); - if (!dbus_message_get_args (message, NULL, - DBUS_TYPE_INT32, &our_int, - DBUS_TYPE_STRING, &our_str, - DBUS_TYPE_DOUBLE, &our_double, - DBUS_TYPE_BOOLEAN, &our_bool, - 0)) - _dbus_assert_not_reached ("Could not get arguments"); + verify_test_message (message); - if (our_int != -0x12345678) - _dbus_assert_not_reached ("integers differ!"); + copy = dbus_message_copy (message); + + _dbus_assert (message->client_serial == copy->client_serial); + _dbus_assert (message->reply_serial == copy->reply_serial); + _dbus_assert (message->header_padding == copy->header_padding); + + _dbus_assert (_dbus_string_get_length (&message->header) == + _dbus_string_get_length (©->header)); - if (our_double != 3.14159) - _dbus_assert_not_reached ("doubles differ!"); + _dbus_assert (_dbus_string_get_length (&message->body) == + _dbus_string_get_length (©->body)); - if (strcmp (our_str, "Test string") != 0) - _dbus_assert_not_reached ("strings differ!"); + verify_test_message (copy); - if (!our_bool) - _dbus_assert_not_reached ("booleans differ"); + name1 = dbus_message_get_name (message); + name2 = dbus_message_get_name (copy); + + _dbus_assert (strcmp (name1, name2) == 0); - dbus_free (our_str); dbus_message_unref (message); + dbus_message_unref (copy); message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage"); _dbus_message_set_serial (message, 1); diff --git a/dbus/dbus-message.h b/dbus/dbus-message.h index d30a0a3d..1d5bbeb8 100644 --- a/dbus/dbus-message.h +++ b/dbus/dbus-message.h @@ -43,7 +43,7 @@ DBusMessage* dbus_message_new_reply (DBusMessage *original_message) DBusMessage* dbus_message_new_error_reply (DBusMessage *original_message, const char *error_name, const char *error_message); -DBusMessage *dbus_message_new_from_message (const DBusMessage *message); +DBusMessage *dbus_message_copy (const DBusMessage *message); void dbus_message_ref (DBusMessage *message); void dbus_message_unref (DBusMessage *message); diff --git a/dbus/dbus-server-debug.c b/dbus/dbus-server-debug.c index 5f79e81c..b1318e32 100644 --- a/dbus/dbus-server-debug.c +++ b/dbus/dbus-server-debug.c @@ -181,7 +181,7 @@ typedef struct { DBusServer *server; DBusTransport *transport; - + DBusTimeout *timeout; } ServerAndTransport; static void @@ -190,12 +190,13 @@ handle_new_client (void *data) ServerAndTransport *st = data; DBusTransport *transport; DBusConnection *connection; + + _dbus_verbose (" new debug client transport %p connecting to server\n", + st->transport); transport = _dbus_transport_debug_server_new (st->transport); if (transport == NULL) - { - return; - } + return; connection = _dbus_connection_new_for_transport (transport); _dbus_transport_unref (transport); @@ -214,9 +215,14 @@ handle_new_client (void *data) st->server->new_connection_data); dbus_server_unref (st->server); } + + _dbus_server_remove_timeout (st->server, st->timeout); /* If no one grabbed a reference, the connection will die. */ dbus_connection_unref (connection); + + /* killing timeout frees both "st" and "timeout" */ + _dbus_timeout_unref (st->timeout); } /** @@ -231,7 +237,6 @@ dbus_bool_t _dbus_server_debug_accept_transport (DBusServer *server, DBusTransport *transport) { - DBusTimeout *timeout = NULL; ServerAndTransport *st = NULL; st = dbus_new (ServerAndTransport, 1); @@ -241,22 +246,21 @@ _dbus_server_debug_accept_transport (DBusServer *server, st->transport = transport; st->server = server; - timeout = _dbus_timeout_new (DEFAULT_INTERVAL, handle_new_client, st, dbus_free); + st->timeout = _dbus_timeout_new (DEFAULT_INTERVAL, handle_new_client, st, + dbus_free); - if (timeout == NULL) + if (st->timeout == NULL) goto failed; - if (!_dbus_server_add_timeout (server, timeout)) + if (!_dbus_server_add_timeout (server, st->timeout)) goto failed; - - _dbus_timeout_unref (timeout); return TRUE; failed: + if (st->timeout) + _dbus_timeout_unref (st->timeout); dbus_free (st); - if (timeout) - _dbus_timeout_unref (timeout); return FALSE; } diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index cfcc0dd5..a5e5e2b7 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -145,8 +145,10 @@ _dbus_server_remove_watch (DBusServer *server, } /** - * Adds a timeout for this server, chaining out to application-provided - * timeout handlers. The timeout will fire only one time. + * Adds a timeout for this server, chaining out to + * application-provided timeout handlers. The timeout should be + * repeatedly handled with dbus_timeout_handle() at its given interval + * until it is removed. * * @param server the server. * @param timeout the timeout to add. diff --git a/dbus/dbus-timeout.c b/dbus/dbus-timeout.c index 408de422..09e54b31 100644 --- a/dbus/dbus-timeout.c +++ b/dbus/dbus-timeout.c @@ -319,7 +319,10 @@ _dbus_timeout_list_remove_timeout (DBusTimeoutList *timeout_list, */ /** - * Gets the timeout interval. + * Gets the timeout interval. The dbus_timeout_handle() + * should be called each time this interval elapses, + * starting after it elapses once. + * * @param timeout the DBusTimeout object. * @returns the interval in milliseconds. */ diff --git a/dbus/dbus-timeout.h b/dbus/dbus-timeout.h index 9de12e8f..2d7112a7 100644 --- a/dbus/dbus-timeout.h +++ b/dbus/dbus-timeout.h @@ -41,7 +41,6 @@ DBusTimeout* _dbus_timeout_new (int interval, void _dbus_timeout_ref (DBusTimeout *timeout); void _dbus_timeout_unref (DBusTimeout *timeout); - DBusTimeoutList *_dbus_timeout_list_new (void); void _dbus_timeout_list_free (DBusTimeoutList *timeout_list); dbus_bool_t _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list, diff --git a/dbus/dbus-transport-debug.c b/dbus/dbus-transport-debug.c index cb4b3c2c..42d1efdc 100644 --- a/dbus/dbus-transport-debug.c +++ b/dbus/dbus-transport-debug.c @@ -2,6 +2,7 @@ /* dbus-transport-debug.c In-proc debug subclass of DBusTransport * * Copyright (C) 2003 CodeFactory AB + * Copyright (C) 2003 Red Hat, Inc. * * Licensed under the Academic Free License version 1.2 * @@ -47,6 +48,13 @@ #define DEFAULT_INTERVAL 1 /** + * Hack due to lack of OOM handling in a couple places + */ +#define WAIT_FOR_MEMORY() _dbus_sleep_milliseconds (250) + +static void check_timeout (DBusTransport *transport); + +/** * Opaque object representing a debug transport. * */ @@ -59,96 +67,21 @@ struct DBusTransportDebug { DBusTransport base; /**< Parent instance */ - DBusTimeout *write_timeout; /**< Timeout for reading. */ - DBusTimeout *read_timeout; /**< Timeout for writing. */ + DBusTimeout *timeout; /**< Timeout for moving messages. */ DBusTransport *other_end; /**< The transport that this transport is connected to. */ -}; - -static void -debug_finalize (DBusTransport *transport) -{ - _dbus_transport_finalize_base (transport); - dbus_free (transport); -} - -static void -do_reading (DBusTransport *transport) -{ - DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport; - - if (transport->disconnected) - return; - - /* Now dispatch the messages */ - if (dbus_connection_dispatch_message (transport->connection)) - { - debug_transport->read_timeout = - _dbus_timeout_new (DEFAULT_INTERVAL, (DBusTimeoutHandler)do_reading, - transport, NULL); - if (!_dbus_connection_add_timeout (transport->connection, - debug_transport->read_timeout)) - { - _dbus_timeout_unref (debug_transport->read_timeout); - debug_transport->read_timeout = NULL; - } - } -} + unsigned int timeout_added : 1; /**< Whether timeout has been added */ +}; -static void -check_read_timeout (DBusTransport *transport) +/* move messages in both directions */ +static dbus_bool_t +move_messages (DBusTransport *transport) { DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport; - dbus_bool_t need_read_timeout; - - if (transport->connection == NULL) - return; - - _dbus_transport_ref (transport); - - need_read_timeout = dbus_connection_get_n_messages (transport->connection) > 0; if (transport->disconnected) - need_read_timeout = FALSE; - - if (need_read_timeout && - debug_transport->read_timeout == NULL) - { - debug_transport->read_timeout = - _dbus_timeout_new (DEFAULT_INTERVAL, (DBusTimeoutHandler)do_reading, - transport, NULL); - - if (debug_transport->read_timeout == NULL) - goto out; - - if (!_dbus_connection_add_timeout (transport->connection, - debug_transport->read_timeout)) - { - _dbus_timeout_unref (debug_transport->read_timeout); - debug_transport->read_timeout = NULL; - - goto out; - } - } - else if (!need_read_timeout && - debug_transport->read_timeout != NULL) - { - _dbus_connection_remove_timeout (transport->connection, - debug_transport->read_timeout); - _dbus_timeout_unref (debug_transport->read_timeout); - debug_transport->read_timeout = NULL; - } - - out: - _dbus_transport_unref (transport); -} - -static void -do_writing (DBusTransport *transport) -{ - if (transport->disconnected) - return; + return TRUE; while (!transport->disconnected && _dbus_connection_have_messages_to_send (transport->connection)) @@ -156,65 +89,106 @@ do_writing (DBusTransport *transport) DBusMessage *message, *copy; message = _dbus_connection_get_message_to_send (transport->connection); - _dbus_message_lock (message); + _dbus_assert (message != NULL); - copy = dbus_message_new_from_message (message); + copy = dbus_message_copy (message); + if (copy == NULL) + return FALSE; + + _dbus_message_lock (message); _dbus_connection_message_sent (transport->connection, message); + + _dbus_verbose (" -->transporting message %s from %s %p to %s %p\n", + dbus_message_get_name (copy), + transport->is_server ? "server" : "client", + transport->connection, + debug_transport->other_end->is_server ? "server" : "client", + debug_transport->other_end->connection); - _dbus_connection_queue_received_message (((DBusTransportDebug *)transport)->other_end->connection, + _dbus_connection_queue_received_message (debug_transport->other_end->connection, copy); dbus_message_unref (copy); } - check_read_timeout (((DBusTransportDebug *)transport)->other_end); + if (debug_transport->other_end && + !debug_transport->other_end->disconnected && + _dbus_connection_have_messages_to_send (debug_transport->other_end->connection)) + { + if (!move_messages (debug_transport->other_end)) + return FALSE; + } + + return TRUE; } static void -check_write_timeout (DBusTransport *transport) +timeout_handler (void *data) { - DBusTransportDebug *debug_transport = (DBusTransportDebug *)transport; - dbus_bool_t need_write_timeout; + DBusTransport *transport = data; - if (transport->connection == NULL) - return; + while (!move_messages (transport)) + WAIT_FOR_MEMORY (); - _dbus_transport_ref (transport); + check_timeout (transport); +} - need_write_timeout = transport->messages_need_sending; +static void +check_timeout (DBusTransport *transport) +{ + DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport; - if (transport->disconnected) - need_write_timeout = FALSE; - - if (need_write_timeout && - debug_transport->write_timeout == NULL) + if (transport->connection && + transport->authenticated && + (transport->messages_need_sending || + (debug_transport->other_end && + debug_transport->other_end->messages_need_sending))) { - debug_transport->write_timeout = - _dbus_timeout_new (DEFAULT_INTERVAL, (DBusTimeoutHandler)do_writing, - transport, NULL); - - if (debug_transport->write_timeout == NULL) - goto out; - - if (!_dbus_connection_add_timeout (transport->connection, - debug_transport->write_timeout)) - { - _dbus_timeout_unref (debug_transport->write_timeout); - debug_transport->write_timeout = NULL; - } + if (!debug_transport->timeout_added) + { + /* FIXME; messages_pending is going to have to + * handle OOM somehow (probably being part of + * PreallocatedSend). See also dbus-transport-unix.c + * check_write_watch() + */ + while (!_dbus_connection_add_timeout (transport->connection, + debug_transport->timeout)) + WAIT_FOR_MEMORY (); + debug_transport->timeout_added = TRUE; + } } - else if (!need_write_timeout && - debug_transport->write_timeout != NULL) + else { - _dbus_connection_remove_timeout (transport->connection, - debug_transport->write_timeout); - _dbus_timeout_unref (debug_transport->write_timeout); - debug_transport->write_timeout = NULL; + if (debug_transport->timeout_added) + { + _dbus_connection_remove_timeout (transport->connection, + debug_transport->timeout); + debug_transport->timeout_added = FALSE; + } } +} - out: - _dbus_transport_unref (transport); +static void +debug_finalize (DBusTransport *transport) +{ + DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport; + + if (debug_transport->timeout_added) + _dbus_connection_remove_timeout (transport->connection, + debug_transport->timeout); + + if (debug_transport->other_end) + { + _dbus_transport_disconnect (debug_transport->other_end); + debug_transport->other_end = NULL; + } + + _dbus_transport_finalize_base (transport); + + _dbus_timeout_unref (debug_transport->timeout); + + dbus_free (transport); } static void @@ -232,13 +206,14 @@ debug_disconnect (DBusTransport *transport) static void debug_connection_set (DBusTransport *transport) { + check_timeout (transport); } static void debug_messages_pending (DBusTransport *transport, int messages_pending) { - check_write_timeout (transport); + check_timeout (transport); } static void @@ -246,6 +221,7 @@ debug_do_iteration (DBusTransport *transport, unsigned int flags, int timeout_milliseconds) { + move_messages (transport); } static void @@ -263,6 +239,16 @@ static DBusTransportVTable debug_vtable = { debug_live_messages_changed }; +static dbus_bool_t +create_timeout_object (DBusTransportDebug *debug_transport) +{ + debug_transport->timeout = _dbus_timeout_new (DEFAULT_INTERVAL, + timeout_handler, + debug_transport, NULL); + + return debug_transport->timeout != NULL; +} + /** * Creates a new debug server transport. * @@ -288,11 +274,21 @@ _dbus_transport_debug_server_new (DBusTransport *client) return NULL; } + if (!create_timeout_object (debug_transport)) + { + _dbus_transport_finalize_base (&debug_transport->base); + dbus_free (debug_transport); + return NULL; + } + debug_transport->base.authenticated = TRUE; /* Connect the two transports */ debug_transport->other_end = client; ((DBusTransportDebug *)client)->other_end = (DBusTransport *)debug_transport; + + _dbus_verbose (" new debug server transport %p created, other end %p\n", + debug_transport, debug_transport->other_end); return (DBusTransport *)debug_transport; } @@ -335,19 +331,30 @@ _dbus_transport_debug_client_new (const char *server_name, dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return NULL; } - - if (!_dbus_server_debug_accept_transport (debug_server, (DBusTransport *)debug_transport)) + + if (!create_timeout_object (debug_transport)) { _dbus_transport_finalize_base (&debug_transport->base); - - dbus_free (debug_transport); - dbus_set_result (result, DBUS_RESULT_IO_ERROR); + dbus_free (debug_transport); + dbus_set_result (result, DBUS_RESULT_NO_MEMORY); + return NULL; + } + + if (!_dbus_server_debug_accept_transport (debug_server, + (DBusTransport *)debug_transport)) + { + _dbus_timeout_unref (debug_transport->timeout); + _dbus_transport_finalize_base (&debug_transport->base); + dbus_free (debug_transport); + dbus_set_result (result, DBUS_RESULT_NO_MEMORY); return NULL; - } /* FIXME: Prolly wrong to do this. */ debug_transport->base.authenticated = TRUE; + + _dbus_verbose (" new debug client transport %p created, other end %p\n", + debug_transport, debug_transport->other_end); return (DBusTransport *)debug_transport; } diff --git a/dbus/dbus-transport-unix.c b/dbus/dbus-transport-unix.c index 81c18b4a..a2b8a384 100644 --- a/dbus/dbus-transport-unix.c +++ b/dbus/dbus-transport-unix.c @@ -136,7 +136,12 @@ check_write_watch (DBusTransport *transport) _dbus_watch_new (unix_transport->fd, DBUS_WATCH_WRITABLE); - /* we can maybe add it some other time, just silently bomb */ + /* FIXME this is total crack. The proper fix is probably to + * allocate the write watch on transport creation, keep it + * allocated. But that doesn't solve needing memory to add the + * watch. messages_pending is going to have to handle OOM + * somehow (probably being part of PreallocatedSend) + */ if (unix_transport->write_watch == NULL) goto out; |