2003-04-09 Havoc Pennington <hp@redhat.com>

* test/test-utils.c: use dispatch status function to fix this up

	* bus/connection.c (connection_watch_callback): don't dispatch
	from here
	(connection_timeout_callback): don't dispatch from here
	(bus_connections_setup_connection): set the dispatch status function
	(bus_connection_disconnected): unset it

	* dbus/dbus-mainloop.c (_dbus_loop_queue_dispatch): new function
	used to add a connection to be dispatched
	(_dbus_loop_iterate): do the dispatching at the end of each
	iteration

	* dbus/dbus-connection.c
	(dbus_connection_set_dispatch_status_function): new function
	allowing us to fix up main loop usage
	(_dbus_connection_last_unref): free all the various function
	user data
	(dbus_connection_dispatch): call the DispatchStatusFunction
	whenever this function returns
	(dbus_connection_handle_watch): call DispatchStatusFunction
	(dbus_connection_send_with_reply_and_block): call DispatchStatusFunction
	(reply_handler_timeout): call DispatchStatusFunction
	(dbus_connection_flush): call DispatchStatusFunction
This commit is contained in:
Havoc Pennington 2003-04-09 22:15:05 +00:00
parent 1708094c0e
commit 7caf646fdf
7 changed files with 352 additions and 119 deletions

View file

@ -1,3 +1,30 @@
2003-04-09 Havoc Pennington <hp@redhat.com>
* test/test-utils.c: use dispatch status function to fix this up
* bus/connection.c (connection_watch_callback): don't dispatch
from here
(connection_timeout_callback): don't dispatch from here
(bus_connections_setup_connection): set the dispatch status function
(bus_connection_disconnected): unset it
* dbus/dbus-mainloop.c (_dbus_loop_queue_dispatch): new function
used to add a connection to be dispatched
(_dbus_loop_iterate): do the dispatching at the end of each
iteration
* dbus/dbus-connection.c
(dbus_connection_set_dispatch_status_function): new function
allowing us to fix up main loop usage
(_dbus_connection_last_unref): free all the various function
user data
(dbus_connection_dispatch): call the DispatchStatusFunction
whenever this function returns
(dbus_connection_handle_watch): call DispatchStatusFunction
(dbus_connection_send_with_reply_and_block): call DispatchStatusFunction
(reply_handler_timeout): call DispatchStatusFunction
(dbus_connection_flush): call DispatchStatusFunction
2003-04-09 Havoc Pennington <hp@redhat.com>
* dbus/dbus-bus.c (dbus_bus_register): fix up error handling and

View file

@ -170,6 +170,9 @@ bus_connection_disconnected (DBusConnection *connection)
dbus_connection_set_unix_user_function (connection,
NULL, NULL, NULL);
dbus_connection_set_dispatch_status_function (connection,
NULL, NULL, NULL);
bus_connection_remove_transactions (connection);
@ -190,15 +193,9 @@ connection_watch_callback (DBusWatch *watch,
{
DBusConnection *connection = data;
dbus_bool_t retval;
dbus_connection_ref (connection);
retval = dbus_connection_handle_watch (connection, watch, condition);
bus_connection_dispatch_all_messages (connection);
dbus_connection_unref (connection);
return retval;
}
@ -229,14 +226,8 @@ connection_timeout_callback (DBusTimeout *timeout,
{
DBusConnection *connection = data;
dbus_connection_ref (connection);
/* can return FALSE on OOM but we just let it fire again later */
dbus_timeout_handle (timeout);
bus_connection_dispatch_all_messages (connection);
dbus_connection_unref (connection);
}
static dbus_bool_t
@ -259,6 +250,20 @@ remove_connection_timeout (DBusTimeout *timeout,
timeout, connection_timeout_callback, connection);
}
static void
dispatch_status_function (DBusConnection *connection,
DBusDispatchStatus new_status,
void *data)
{
DBusLoop *loop = data;
if (new_status != DBUS_DISPATCH_COMPLETE)
{
while (!_dbus_loop_queue_dispatch (loop, connection))
_dbus_wait_for_memory ();
}
}
static dbus_bool_t
allow_user_function (DBusConnection *connection,
unsigned long uid,
@ -405,6 +410,11 @@ bus_connections_setup_connection (BusConnections *connections,
dbus_connection_set_unix_user_function (connection,
allow_user_function,
NULL, NULL);
dbus_connection_set_dispatch_status_function (connection,
dispatch_status_function,
bus_context_get_loop (connections->context),
NULL);
/* Setup the connection with the dispatcher */
if (!bus_dispatch_add_connection (connection))
@ -415,6 +425,15 @@ bus_connections_setup_connection (BusConnections *connections,
bus_dispatch_remove_connection (connection);
goto out;
}
if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
{
if (!_dbus_loop_queue_dispatch (bus_context_get_loop (connections->context), connection))
{
bus_dispatch_remove_connection (connection);
goto out;
}
}
dbus_connection_ref (connection);
retval = TRUE;
@ -437,6 +456,9 @@ bus_connections_setup_connection (BusConnections *connections,
dbus_connection_set_unix_user_function (connection,
NULL, NULL, NULL);
dbus_connection_set_dispatch_status_function (connection,
NULL, NULL, NULL);
if (!dbus_connection_set_data (connection,
connection_data_slot,
NULL, NULL))

View file

@ -109,6 +109,12 @@ struct DBusConnection
DBusWakeupMainFunction wakeup_main_function; /**< Function to wake up the mainloop */
void *wakeup_main_data; /**< Application data for wakeup_main_function */
DBusFreeFunction free_wakeup_main_data; /**< free wakeup_main_data */
DBusDispatchStatusFunction dispatch_status_function; /**< Function on dispatch status changes */
void *dispatch_status_data; /**< Application data for dispatch_status_function */
DBusFreeFunction free_dispatch_status_data; /**< free dispatch_status_data */
DBusDispatchStatus last_dispatch_status;
};
typedef struct
@ -126,9 +132,12 @@ typedef struct
static void reply_handler_data_free (ReplyHandlerData *data);
static void _dbus_connection_remove_timeout_locked (DBusConnection *connection,
DBusTimeout *timeout);
static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
static void _dbus_connection_remove_timeout_locked (DBusConnection *connection,
DBusTimeout *timeout);
static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
static void _dbus_connection_update_dispatch_status_locked (DBusConnection *connection,
DBusDispatchStatus new_status);
/**
* Acquires the connection lock.
@ -231,7 +240,7 @@ _dbus_connection_queue_received_message_link (DBusConnection *connection,
connection->n_incoming += 1;
_dbus_connection_wakeup_mainloop (connection);
_dbus_assert (dbus_message_get_name (message) != NULL);
_dbus_verbose ("Message %p (%s) added to incoming queue %p, %d incoming\n",
message, dbus_message_get_name (message),
@ -652,7 +661,8 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
connection->handler_table = handler_table;
connection->pending_replies = pending_replies;
connection->filter_list = NULL;
connection->last_dispatch_status = DBUS_DISPATCH_COMPLETE; /* so we're notified first time there's data */
_dbus_data_slot_list_init (&connection->slot_list);
connection->client_serial = 1;
@ -887,6 +897,11 @@ _dbus_connection_last_unref (DBusConnection *connection)
_dbus_counter_unref (connection->connection_counter);
connection->connection_counter = NULL;
}
/* ---- We're going to call various application callbacks here, hope it doesn't break anything... */
dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
dbus_connection_set_wakeup_main_function (connection, NULL, NULL, NULL);
dbus_connection_set_unix_user_function (connection, NULL, NULL, NULL);
_dbus_watch_list_free (connection->watches);
connection->watches = NULL;
@ -894,8 +909,8 @@ _dbus_connection_last_unref (DBusConnection *connection)
_dbus_timeout_list_free (connection->timeouts);
connection->timeouts = NULL;
/* calls out to application code... */
_dbus_data_slot_list_free (&connection->slot_list);
/* ---- Done with stuff that invokes application callbacks */
_dbus_hash_iter_init (connection->handler_table, &iter);
while (_dbus_hash_iter_next (&iter))
@ -1184,6 +1199,7 @@ reply_handler_timeout (void *data)
{
DBusConnection *connection;
ReplyHandlerData *reply_handler_data = data;
DBusDispatchStatus status;
connection = reply_handler_data->connection;
@ -1198,9 +1214,13 @@ reply_handler_timeout (void *data)
_dbus_connection_remove_timeout (connection,
reply_handler_data->timeout);
reply_handler_data->timeout_added = FALSE;
status = _dbus_connection_get_dispatch_status_unlocked (connection);
dbus_mutex_unlock (connection->mutex);
_dbus_connection_update_dispatch_status_locked (connection, status);
return TRUE;
}
@ -1488,11 +1508,15 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
reply = check_for_reply_unlocked (connection, client_serial);
if (reply != NULL)
{
{
status = _dbus_connection_get_dispatch_status_unlocked (connection);
dbus_mutex_unlock (connection->mutex);
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply %s\n",
dbus_message_get_name (reply));
_dbus_connection_update_dispatch_status_locked (connection, status);
return reply;
}
@ -1549,6 +1573,8 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
dbus_mutex_unlock (connection->mutex);
_dbus_connection_update_dispatch_status_locked (connection, status);
return NULL;
}
@ -1560,11 +1586,12 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
void
dbus_connection_flush (DBusConnection *connection)
{
/* We have to specify DBUS_ITERATION_DO_READING here
* because otherwise we could have two apps deadlock
* if they are both doing a flush(), and the kernel
* buffers fill up.
/* We have to specify DBUS_ITERATION_DO_READING here because
* otherwise we could have two apps deadlock if they are both doing
* a flush(), and the kernel buffers fill up. This could change the
* dispatch status.
*/
DBusDispatchStatus status;
dbus_mutex_lock (connection->mutex);
while (connection->n_outgoing > 0)
@ -1573,7 +1600,12 @@ dbus_connection_flush (DBusConnection *connection)
DBUS_ITERATION_DO_WRITING |
DBUS_ITERATION_BLOCK,
-1);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
dbus_mutex_unlock (connection->mutex);
_dbus_connection_update_dispatch_status_locked (connection, status);
}
/* Call with mutex held. Will drop it while waiting and re-acquire
@ -1818,6 +1850,40 @@ _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
}
}
static void
_dbus_connection_update_dispatch_status_locked (DBusConnection *connection,
DBusDispatchStatus new_status)
{
dbus_bool_t changed;
DBusDispatchStatusFunction function;
void *data;
dbus_mutex_lock (connection->mutex);
_dbus_connection_ref_unlocked (connection);
changed = new_status != connection->last_dispatch_status;
connection->last_dispatch_status = new_status;
function = connection->dispatch_status_function;
data = connection->dispatch_status_data;
dbus_mutex_unlock (connection->mutex);
if (changed && function)
{
_dbus_verbose ("Notifying of change to dispatch status of %p now %d (%s)\n",
connection, new_status,
new_status == DBUS_DISPATCH_COMPLETE ? "complete" :
new_status == DBUS_DISPATCH_DATA_REMAINS ? "data remains" :
new_status == DBUS_DISPATCH_NEED_MEMORY ? "need memory" :
"???");
(* function) (connection, new_status, data);
}
dbus_connection_unref (connection);
}
/**
* Gets the current state (what we would currently return
* from dbus_connection_dispatch()) but doesn't actually
@ -1864,7 +1930,10 @@ dbus_connection_dispatch (DBusConnection *connection)
status = dbus_connection_get_dispatch_status (connection);
if (status != DBUS_DISPATCH_DATA_REMAINS)
return status;
{
_dbus_connection_update_dispatch_status_locked (connection, status);
return status;
}
dbus_mutex_lock (connection->mutex);
@ -1891,8 +1960,10 @@ dbus_connection_dispatch (DBusConnection *connection)
status = dbus_connection_get_dispatch_status (connection);
_dbus_connection_update_dispatch_status_locked (connection, status);
dbus_connection_unref (connection);
return status;
}
@ -1909,7 +1980,11 @@ dbus_connection_dispatch (DBusConnection *connection)
_dbus_connection_release_dispatch (connection);
dbus_mutex_unlock (connection->mutex);
_dbus_connection_failed_pop (connection, message_link);
_dbus_connection_update_dispatch_status_locked (connection, DBUS_DISPATCH_NEED_MEMORY);
dbus_connection_unref (connection);
return DBUS_DISPATCH_NEED_MEMORY;
}
@ -2012,6 +2087,8 @@ dbus_connection_dispatch (DBusConnection *connection)
*/
status = dbus_connection_get_dispatch_status (connection);
_dbus_connection_update_dispatch_status_locked (connection, status);
dbus_connection_unref (connection);
@ -2200,6 +2277,46 @@ dbus_connection_set_wakeup_main_function (DBusConnection *connection,
(*old_free_data) (old_data);
}
/**
* Set a function to be invoked when the dispatch status changes.
* If the dispatch status is #DBUS_DISPATCH_DATA_REMAINS, then
* dbus_connection_dispatch() needs to be called to process incoming
* messages. However, dbus_connection_dispatch() MUST NOT BE CALLED
* from inside the DBusDispatchStatusFunction. Indeed, almost
* any reentrancy in this function is a bad idea. Instead,
* the DBusDispatchStatusFunction should simply save an indication
* that messages should be dispatched later, when the main loop
* is re-entered.
*
* @param connection the connection
* @param function function to call on dispatch status changes
* @param data data for function
* @param free_data_function free the function data
*/
void
dbus_connection_set_dispatch_status_function (DBusConnection *connection,
DBusDispatchStatusFunction function,
void *data,
DBusFreeFunction free_data_function)
{
void *old_data;
DBusFreeFunction old_free_data;
dbus_mutex_lock (connection->mutex);
old_data = connection->dispatch_status_data;
old_free_data = connection->free_dispatch_status_data;
connection->dispatch_status_function = function;
connection->dispatch_status_data = data;
connection->free_dispatch_status_data = free_data_function;
dbus_mutex_unlock (connection->mutex);
/* Callback outside the lock */
if (old_free_data)
(*old_free_data) (old_data);
}
/**
* Called to notify the connection when a previously-added watch
* is ready for reading or writing, or has an exception such
@ -2223,14 +2340,20 @@ dbus_connection_handle_watch (DBusConnection *connection,
unsigned int condition)
{
dbus_bool_t retval;
DBusDispatchStatus status;
dbus_mutex_lock (connection->mutex);
_dbus_connection_acquire_io_path (connection, -1);
retval = _dbus_transport_handle_watch (connection->transport,
watch, condition);
_dbus_connection_release_io_path (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
dbus_mutex_unlock (connection->mutex);
_dbus_connection_update_dispatch_status_locked (connection, status);
return retval;
}

View file

@ -75,63 +75,71 @@ typedef void (* DBusTimeoutToggledFunction) (DBusTimeout *timeout,
void *data);
typedef void (* DBusRemoveTimeoutFunction) (DBusTimeout *timeout,
void *data);
typedef void (* DBusDispatchStatusFunction) (DBusConnection *connection,
DBusDispatchStatus new_status,
void *data);
typedef void (* DBusWakeupMainFunction) (void *data);
typedef dbus_bool_t (* DBusAllowUnixUserFunction) (DBusConnection *connection,
unsigned long uid,
void *data);
DBusConnection* dbus_connection_open (const char *address,
DBusError *error);
void dbus_connection_ref (DBusConnection *connection);
void dbus_connection_unref (DBusConnection *connection);
void dbus_connection_disconnect (DBusConnection *connection);
dbus_bool_t dbus_connection_get_is_connected (DBusConnection *connection);
dbus_bool_t dbus_connection_get_is_authenticated (DBusConnection *connection);
void dbus_connection_flush (DBusConnection *connection);
DBusMessage* dbus_connection_borrow_message (DBusConnection *connection);
void dbus_connection_return_message (DBusConnection *connection,
DBusMessage *message);
void dbus_connection_steal_borrowed_message (DBusConnection *connection,
DBusMessage *message);
DBusMessage* dbus_connection_pop_message (DBusConnection *connection);
DBusDispatchStatus dbus_connection_get_dispatch_status (DBusConnection *connection);
DBusDispatchStatus dbus_connection_dispatch (DBusConnection *connection);
dbus_bool_t dbus_connection_send (DBusConnection *connection,
DBusMessage *message,
dbus_int32_t *client_serial);
dbus_bool_t dbus_connection_send_with_reply (DBusConnection *connection,
DBusMessage *message,
DBusMessageHandler *reply_handler,
int timeout_milliseconds);
DBusMessage * dbus_connection_send_with_reply_and_block (DBusConnection *connection,
DBusMessage *message,
int timeout_milliseconds,
DBusError *error);
dbus_bool_t dbus_connection_set_watch_functions (DBusConnection *connection,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
DBusWatchToggledFunction toggled_function,
void *data,
DBusFreeFunction free_data_function);
dbus_bool_t dbus_connection_set_timeout_functions (DBusConnection *connection,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_function,
DBusTimeoutToggledFunction toggled_function,
void *data,
DBusFreeFunction free_data_function);
void dbus_connection_set_wakeup_main_function (DBusConnection *connection,
DBusWakeupMainFunction wakeup_main_function,
void *data,
DBusFreeFunction free_data_function);
dbus_bool_t dbus_connection_handle_watch (DBusConnection *connection,
DBusWatch *watch,
unsigned int condition);
dbus_bool_t dbus_connection_get_unix_user (DBusConnection *connection,
unsigned long *uid);
void dbus_connection_set_unix_user_function (DBusConnection *connection,
DBusAllowUnixUserFunction function,
void *data,
DBusFreeFunction free_data_function);
DBusConnection* dbus_connection_open (const char *address,
DBusError *error);
void dbus_connection_ref (DBusConnection *connection);
void dbus_connection_unref (DBusConnection *connection);
void dbus_connection_disconnect (DBusConnection *connection);
dbus_bool_t dbus_connection_get_is_connected (DBusConnection *connection);
dbus_bool_t dbus_connection_get_is_authenticated (DBusConnection *connection);
void dbus_connection_flush (DBusConnection *connection);
DBusMessage* dbus_connection_borrow_message (DBusConnection *connection);
void dbus_connection_return_message (DBusConnection *connection,
DBusMessage *message);
void dbus_connection_steal_borrowed_message (DBusConnection *connection,
DBusMessage *message);
DBusMessage* dbus_connection_pop_message (DBusConnection *connection);
DBusDispatchStatus dbus_connection_get_dispatch_status (DBusConnection *connection);
DBusDispatchStatus dbus_connection_dispatch (DBusConnection *connection);
dbus_bool_t dbus_connection_send (DBusConnection *connection,
DBusMessage *message,
dbus_int32_t *client_serial);
dbus_bool_t dbus_connection_send_with_reply (DBusConnection *connection,
DBusMessage *message,
DBusMessageHandler *reply_handler,
int timeout_milliseconds);
DBusMessage * dbus_connection_send_with_reply_and_block (DBusConnection *connection,
DBusMessage *message,
int timeout_milliseconds,
DBusError *error);
dbus_bool_t dbus_connection_set_watch_functions (DBusConnection *connection,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
DBusWatchToggledFunction toggled_function,
void *data,
DBusFreeFunction free_data_function);
dbus_bool_t dbus_connection_set_timeout_functions (DBusConnection *connection,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_function,
DBusTimeoutToggledFunction toggled_function,
void *data,
DBusFreeFunction free_data_function);
void dbus_connection_set_wakeup_main_function (DBusConnection *connection,
DBusWakeupMainFunction wakeup_main_function,
void *data,
DBusFreeFunction free_data_function);
void dbus_connection_set_dispatch_status_function (DBusConnection *connection,
DBusDispatchStatusFunction function,
void *data,
DBusFreeFunction free_data_function);
dbus_bool_t dbus_connection_handle_watch (DBusConnection *connection,
DBusWatch *watch,
unsigned int condition);
dbus_bool_t dbus_connection_get_unix_user (DBusConnection *connection,
unsigned long *uid);
void dbus_connection_set_unix_user_function (DBusConnection *connection,
DBusAllowUnixUserFunction function,
void *data,
DBusFreeFunction free_data_function);
int dbus_watch_get_fd (DBusWatch *watch);
unsigned int dbus_watch_get_flags (DBusWatch *watch);

View file

@ -34,6 +34,7 @@ struct DBusLoop
int watch_count;
int timeout_count;
int depth; /**< number of recursive runs */
DBusList *need_dispatch;
};
typedef enum
@ -199,6 +200,12 @@ _dbus_loop_unref (DBusLoop *loop)
loop->refcount -= 1;
if (loop->refcount == 0)
{
while (loop->need_dispatch)
{
DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch);
dbus_connection_unref (connection);
}
dbus_free (loop);
}
@ -399,13 +406,55 @@ check_timeout (unsigned long tv_sec,
return msec == 0;
}
static void
_dbus_loop_dispatch (DBusLoop *loop)
{
next:
while (loop->need_dispatch != NULL)
{
DBusConnection *connection = _dbus_list_pop_first (&loop->need_dispatch);
while (TRUE)
{
DBusDispatchStatus status;
status = dbus_connection_dispatch (connection);
if (status == DBUS_DISPATCH_COMPLETE)
{
dbus_connection_unref (connection);
goto next;
}
else
{
if (status == DBUS_DISPATCH_NEED_MEMORY)
_dbus_wait_for_memory ();
}
}
}
}
dbus_bool_t
_dbus_loop_queue_dispatch (DBusLoop *loop,
DBusConnection *connection)
{
if (_dbus_list_append (&loop->need_dispatch, connection))
{
dbus_connection_ref (connection);
return TRUE;
}
else
return FALSE;
}
/* Returns TRUE if we have any timeouts or ready file descriptors,
* which is just used in test code as a debug hack
*/
dbus_bool_t
_dbus_loop_iterate (DBusLoop *loop,
dbus_bool_t block)
dbus_bool_t block)
{
dbus_bool_t retval;
DBusPollFD *fds;
@ -553,7 +602,8 @@ _dbus_loop_iterate (DBusLoop *loop,
}
}
if (!block)
/* Never block if we have stuff to dispatch */
if (!block || loop->need_dispatch != NULL)
{
timeout = 0;
#if 0
@ -673,6 +723,12 @@ _dbus_loop_iterate (DBusLoop *loop,
dbus_free (fds);
dbus_free (watches_for_fds);
if (loop->need_dispatch != NULL)
{
retval = TRUE;
_dbus_loop_dispatch (loop);
}
return retval;
}
@ -716,3 +772,4 @@ _dbus_wait_for_memory (void)
{
_dbus_sleep_milliseconds (_dbus_get_oom_wait ());
}

View file

@ -55,6 +55,10 @@ void _dbus_loop_remove_timeout (DBusLoop *loop,
DBusTimeout *timeout,
DBusTimeoutFunction function,
void *data);
dbus_bool_t _dbus_loop_queue_dispatch (DBusLoop *loop,
DBusConnection *connection);
void _dbus_loop_run (DBusLoop *loop);
void _dbus_loop_quit (DBusLoop *loop);
dbus_bool_t _dbus_loop_iterate (DBusLoop *loop,

View file

@ -7,24 +7,6 @@ typedef struct
} CData;
dbus_bool_t
test_connection_dispatch_one_message (DBusConnection *connection)
{
DBusDispatchStatus status;
while ((status = dbus_connection_dispatch (connection)) == DBUS_DISPATCH_NEED_MEMORY)
_dbus_wait_for_memory ();
return status == DBUS_DISPATCH_DATA_REMAINS;
}
void
test_connection_dispatch_all_messages (DBusConnection *connection)
{
while (test_connection_dispatch_one_message (connection))
;
}
static dbus_bool_t
connection_watch_callback (DBusWatch *watch,
unsigned int condition,
@ -32,21 +14,9 @@ connection_watch_callback (DBusWatch *watch,
{
CData *cd = data;
dbus_bool_t retval;
dbus_connection_ref (cd->connection);
_dbus_verbose (" Handling watch\n");
retval = dbus_connection_handle_watch (cd->connection, watch, condition);
_dbus_verbose (" Watch handled\n");
test_connection_dispatch_all_messages (cd->connection);
_dbus_verbose (" Dispatched all\n");
dbus_connection_unref (cd->connection);
return retval;
}
@ -78,14 +48,8 @@ connection_timeout_callback (DBusTimeout *timeout,
{
CData *cd = data;
dbus_connection_ref (cd->connection);
/* Can return FALSE on OOM but we just let it fire again later */
dbus_timeout_handle (timeout);
test_connection_dispatch_all_messages (cd->connection);
dbus_connection_unref (cd->connection);
}
static dbus_bool_t
@ -108,6 +72,20 @@ remove_timeout (DBusTimeout *timeout,
timeout, connection_timeout_callback, cd);
}
static void
dispatch_status_function (DBusConnection *connection,
DBusDispatchStatus new_status,
void *data)
{
DBusLoop *loop = data;
if (new_status != DBUS_DISPATCH_COMPLETE)
{
while (!_dbus_loop_queue_dispatch (loop, connection))
_dbus_wait_for_memory ();
}
}
static void
cdata_free (void *data)
{
@ -144,6 +122,11 @@ test_connection_setup (DBusLoop *loop,
{
CData *cd;
cd = NULL;
dbus_connection_set_dispatch_status_function (connection, dispatch_status_function,
loop, NULL);
cd = cdata_new (loop, connection);
if (cd == NULL)
goto nomem;
@ -170,16 +153,24 @@ test_connection_setup (DBusLoop *loop,
remove_timeout,
NULL,
cd, cdata_free))
{
dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
goto nomem;
}
goto nomem;
if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
{
if (!_dbus_loop_queue_dispatch (loop, connection))
goto nomem;
}
return TRUE;
nomem:
if (cd)
cdata_free (cd);
dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
return FALSE;
}
@ -201,4 +192,5 @@ test_connection_shutdown (DBusLoop *loop,
NULL, NULL))
_dbus_assert_not_reached ("setting timeout functions to NULL failed");
dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
}