summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-03-15 02:19:02 +0000
committerHavoc Pennington <hp@redhat.com>2003-03-15 02:19:02 +0000
commit4c95a9782c65f88e2904c44abeb734a1b00f6353 (patch)
treed81b0c3a3497a031cb642dc5126750a36a6651ff /dbus
parentf468907fb09e8198c4cce7e8f2ddeae8b5476b9e (diff)
2003-03-14 Havoc Pennington <hp@redhat.com>
* dbus/dbus-memory.c: add a "detect buffer overwrites on free" cheesy hack * dbus/dbus-transport-debug.c: rework this a good bit to be less complicated. hopefully still works. * dbus/dbus-server-debug.c (handle_new_client): remove timeout manually * glib/dbus-gmain.c (timeout_handler): don't remove timeout after running it * dbus/dbus-message.c (dbus_message_copy): rename from dbus_message_new_from_message, fix it up to copy all the message fields, add test case * bus/dispatch.c (bus_dispatch_test): add some more test code, not quite passing yet
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-connection.c29
-rw-r--r--dbus/dbus-memory.c178
-rw-r--r--dbus/dbus-message.c79
-rw-r--r--dbus/dbus-message.h2
-rw-r--r--dbus/dbus-server-debug.c28
-rw-r--r--dbus/dbus-server.c6
-rw-r--r--dbus/dbus-timeout.c5
-rw-r--r--dbus/dbus-timeout.h1
-rw-r--r--dbus/dbus-transport-debug.c259
-rw-r--r--dbus/dbus-transport-unix.c7
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 (&copy->header));
- if (our_double != 3.14159)
- _dbus_assert_not_reached ("doubles differ!");
+ _dbus_assert (_dbus_string_get_length (&message->body) ==
+ _dbus_string_get_length (&copy->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;