2003-04-03 Havoc Pennington <hp@redhat.com>
+ * bus/loop.h, bus/loop.c: make the mainloop an object so we can
+ have multiple ones
+
+ * bus/*.[hc]: adapt to mainloop change
+
+2003-04-03 Havoc Pennington <hp@redhat.com>
+
* bus/activation.c (load_directory): fix up memleaks
(bus_activation_entry_free): free the entry
int refcount;
char *type;
char *address;
+ BusLoop *loop;
DBusList *servers;
BusConnections *connections;
BusActivation *activation;
DBusHashTable *rules_by_gid; /**< per-GID policy rules */
};
+static int server_data_slot = -1;
+static int server_data_slot_refcount = 0;
+
+typedef struct
+{
+ BusContext *context;
+} BusServerData;
+
+#define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot))
+
+static dbus_bool_t
+server_data_slot_ref (void)
+{
+ if (server_data_slot < 0)
+ {
+ server_data_slot = dbus_server_allocate_data_slot ();
+
+ if (server_data_slot < 0)
+ return FALSE;
+
+ _dbus_assert (server_data_slot_refcount == 0);
+ }
+
+ server_data_slot_refcount += 1;
+
+ return TRUE;
+}
+
+static void
+server_data_slot_unref (void)
+{
+ _dbus_assert (server_data_slot_refcount > 0);
+
+ server_data_slot_refcount -= 1;
+
+ if (server_data_slot_refcount == 0)
+ {
+ dbus_server_free_data_slot (server_data_slot);
+ server_data_slot = -1;
+ }
+}
+
+static BusContext*
+server_get_context (DBusServer *server)
+{
+ BusContext *context;
+ BusServerData *bd;
+
+ if (!server_data_slot_ref ())
+ return NULL;
+
+ bd = BUS_SERVER_DATA (server);
+ if (bd == NULL)
+ return NULL;
+
+ context = bd->context;
+
+ server_data_slot_unref ();
+
+ return context;
+}
+
static dbus_bool_t
server_watch_callback (DBusWatch *watch,
unsigned int condition,
add_server_watch (DBusWatch *watch,
void *data)
{
- return bus_loop_add_watch (watch, server_watch_callback, data,
+ DBusServer *server = data;
+ BusContext *context;
+
+ context = server_get_context (server);
+
+ return bus_loop_add_watch (context->loop,
+ watch, server_watch_callback, server,
NULL);
}
remove_server_watch (DBusWatch *watch,
void *data)
{
- bus_loop_remove_watch (watch, server_watch_callback, data);
+ DBusServer *server = data;
+ BusContext *context;
+
+ context = server_get_context (server);
+
+ bus_loop_remove_watch (context->loop,
+ watch, server_watch_callback, server);
}
add_server_timeout (DBusTimeout *timeout,
void *data)
{
- return bus_loop_add_timeout (timeout, server_timeout_callback, data, NULL);
+ DBusServer *server = data;
+ BusContext *context;
+
+ context = server_get_context (server);
+
+ return bus_loop_add_timeout (context->loop,
+ timeout, server_timeout_callback, server, NULL);
}
static void
remove_server_timeout (DBusTimeout *timeout,
void *data)
{
- bus_loop_remove_timeout (timeout, server_timeout_callback, data);
+ DBusServer *server = data;
+ BusContext *context;
+
+ context = server_get_context (server);
+
+ bus_loop_remove_timeout (context->loop,
+ timeout, server_timeout_callback, server);
}
static void
dbus_free (list);
}
+static void
+free_server_data (void *data)
+{
+ BusServerData *bd = data;
+
+ dbus_free (bd);
+}
+
static dbus_bool_t
setup_server (BusContext *context,
DBusServer *server,
char **auth_mechanisms,
DBusError *error)
{
+ BusServerData *bd;
+
if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
{
BUS_SET_OOM (error);
BUS_SET_OOM (error);
return FALSE;
}
+
+ bd = dbus_new0 (BusServerData, 1);
+ if (!dbus_server_set_data (server,
+ server_data_slot,
+ bd, free_server_data))
+ {
+ dbus_free (bd);
+ return FALSE;
+ }
+ bd->context = context;
+
return TRUE;
}
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
if (!_dbus_string_init (&full_address))
- return NULL;
-
+ {
+ BUS_SET_OOM (error);
+ return NULL;
+ }
+
+ if (!server_data_slot_ref ())
+ {
+ BUS_SET_OOM (error);
+ _dbus_string_free (&full_address);
+ return NULL;
+ }
+
parser = NULL;
context = NULL;
auth_mechanisms = NULL;
context->refcount = 1;
+ context->loop = bus_loop_new ();
+ if (context->loop == NULL)
+ {
+ BUS_SET_OOM (error);
+ goto failed;
+ }
+
/* Build an array of auth mechanisms */
auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
_dbus_string_free (&full_address);
dbus_free_string_array (auth_mechanisms);
+
+ server_data_slot_unref ();
+
return NULL;
}
context->rules_by_gid = NULL;
}
+ if (context->loop)
+ {
+ bus_loop_unref (context->loop);
+ context->loop = NULL;
+ }
+
dbus_free (context->type);
dbus_free (context->address);
dbus_free (context);
+
+ server_data_slot_unref ();
}
}
return context->activation;
}
+BusLoop*
+bus_context_get_loop (BusContext *context)
+{
+ return context->loop;
+}
+
static dbus_bool_t
list_allows_user (dbus_bool_t def,
DBusList **list,
#include <dbus/dbus.h>
#include <dbus/dbus-string.h>
+#include "loop.h"
+
typedef struct BusActivation BusActivation;
typedef struct BusConnections BusConnections;
typedef struct BusContext BusContext;
BusRegistry* bus_context_get_registry (BusContext *context);
BusConnections* bus_context_get_connections (BusContext *context);
BusActivation* bus_context_get_activation (BusContext *context);
+BusLoop* bus_context_get_loop (BusContext *context);
dbus_bool_t bus_context_allow_user (BusContext *context,
unsigned long uid);
BusPolicy* bus_context_create_connection_policy (BusContext *context,
}
}
+static BusLoop*
+connection_get_loop (DBusConnection *connection)
+{
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+
+ return bus_context_get_loop (d->connections->context);
+}
+
void
bus_connection_disconnected (DBusConnection *connection)
{
static dbus_bool_t
add_connection_watch (DBusWatch *watch,
- DBusConnection *connection)
+ void *data)
{
- return bus_loop_add_watch (watch, connection_watch_callback, connection,
+ DBusConnection *connection = data;
+
+ return bus_loop_add_watch (connection_get_loop (connection),
+ watch, connection_watch_callback, connection,
NULL);
}
static void
remove_connection_watch (DBusWatch *watch,
- DBusConnection *connection)
+ void *data)
{
- bus_loop_remove_watch (watch, connection_watch_callback, connection);
+ DBusConnection *connection = data;
+
+ bus_loop_remove_watch (connection_get_loop (connection),
+ watch, connection_watch_callback, connection);
}
static void
static dbus_bool_t
add_connection_timeout (DBusTimeout *timeout,
- DBusConnection *connection)
+ void *data)
{
- return bus_loop_add_timeout (timeout, connection_timeout_callback, connection, NULL);
+ DBusConnection *connection = data;
+
+ return bus_loop_add_timeout (connection_get_loop (connection),
+ timeout, connection_timeout_callback, connection, NULL);
}
static void
remove_connection_timeout (DBusTimeout *timeout,
- DBusConnection *connection)
+ void *data)
{
- bus_loop_remove_timeout (timeout, connection_timeout_callback, connection);
+ DBusConnection *connection = data;
+
+ bus_loop_remove_timeout (connection_get_loop (connection),
+ timeout, connection_timeout_callback, connection);
}
static dbus_bool_t
d->group_ids = NULL;
if (!dbus_connection_set_watch_functions (connection,
- (DBusAddWatchFunction) add_connection_watch,
- (DBusRemoveWatchFunction) remove_connection_watch,
+ add_connection_watch,
+ remove_connection_watch,
NULL,
connection,
NULL))
goto out;
if (!dbus_connection_set_timeout_functions (connection,
- (DBusAddTimeoutFunction) add_connection_timeout,
- (DBusRemoveTimeoutFunction) remove_connection_timeout,
+ add_connection_timeout,
+ remove_connection_timeout,
NULL,
connection, NULL))
goto out;
out:
if (!retval)
- {
- if (!dbus_connection_set_data (connection,
- connection_data_slot,
- NULL, NULL))
- _dbus_assert_not_reached ("failed to set connection data to null");
-
+ {
if (!dbus_connection_set_watch_functions (connection,
NULL, NULL, NULL,
connection,
dbus_connection_set_unix_user_function (connection,
NULL, NULL, NULL);
+
+ if (!dbus_connection_set_data (connection,
+ connection_data_slot,
+ NULL, NULL))
+ _dbus_assert_not_reached ("failed to set connection data to null");
}
return retval;
/* kick in the disconnect handler that unrefs the connection */
dbus_connection_disconnect (connection);
- bus_test_flush_bus (context);
-
+ bus_test_run_everything (context);
+
_dbus_assert (bus_test_client_listed (connection));
/* Run disconnect handler in test.c */
dbus_message_unref (message);
message = NULL;
-
- bus_test_flush_bus (context);
+
+ bus_test_run_everything (context);
if (!dbus_connection_get_is_connected (connection))
{
dbus_message_unref (message);
message = NULL;
-
- bus_test_flush_bus (context);
+
+ bus_test_run_everything (context);
if (!dbus_connection_get_is_connected (connection))
{
return retval;
}
+#define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_service_activation (BusContext *context,
+ DBusConnection *connection)
+{
+ 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_ACTIVATE_SERVICE);
+
+ if (message == NULL)
+ return TRUE;
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, EXISTENT_SERVICE_NAME,
+ DBUS_TYPE_UINT32, 0,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ if (!dbus_connection_send (connection, message, &serial))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+
+ /* now wait for the message bus to hear back from the activated service */
+ bus_test_run_bus_loop (context);
+
+ /* and process everything again */
+ bus_test_run_everything (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_ACTIVATE_SERVICE, serial, connection);
+ 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_sender_is (message, DBUS_SERVICE_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ goto out;
+ }
+
+ if (dbus_message_name_is (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_name_is (message,
+ DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ _dbus_warn ("Did not expect error %s\n",
+ dbus_message_get_name (message));
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully activate %s\n",
+ EXISTENT_SERVICE_NAME);
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
typedef struct
{
Check1Func func;
if (!check_hello_message (context, baz))
_dbus_assert_not_reached ("hello message failed");
+#if 0
+ check2_try_iterations (context, foo, "existent_service_activation",
+ check_existent_service_activation);
+#endif
+
check2_try_iterations (context, foo, "nonexistent_service_activation",
check_nonexistent_service_activation);
#include <dbus/dbus-list.h>
#include <dbus/dbus-sysdeps.h>
-static DBusList *callbacks = NULL;
-static int callback_list_serial = 0;
-static int watch_count = 0;
-static int timeout_count = 0;
-static dbus_bool_t exited = FALSE;
+struct BusLoop
+{
+ int refcount;
+ DBusList *callbacks;
+ int callback_list_serial;
+ int watch_count;
+ int timeout_count;
+ int depth; /**< number of recursive runs */
+};
typedef enum
{
}
static dbus_bool_t
-add_callback (Callback *cb)
+add_callback (BusLoop *loop,
+ Callback *cb)
{
- if (!_dbus_list_append (&callbacks, cb))
+ if (!_dbus_list_append (&loop->callbacks, cb))
return FALSE;
- callback_list_serial += 1;
+ loop->callback_list_serial += 1;
switch (cb->type)
{
case CALLBACK_WATCH:
- watch_count += 1;
+ loop->watch_count += 1;
break;
case CALLBACK_TIMEOUT:
- timeout_count += 1;
+ loop->timeout_count += 1;
break;
}
}
static void
-remove_callback (DBusList *link)
+remove_callback (BusLoop *loop,
+ DBusList *link)
{
Callback *cb = link->data;
switch (cb->type)
{
case CALLBACK_WATCH:
- watch_count -= 1;
+ loop->watch_count -= 1;
break;
case CALLBACK_TIMEOUT:
- timeout_count -= 1;
+ loop->timeout_count -= 1;
break;
}
callback_free (cb);
- _dbus_list_remove_link (&callbacks, link);
- callback_list_serial += 1;
+ _dbus_list_remove_link (&loop->callbacks, link);
+ loop->callback_list_serial += 1;
+}
+
+BusLoop*
+bus_loop_new (void)
+{
+ BusLoop *loop;
+
+ loop = dbus_new0 (BusLoop, 1);
+ if (loop == NULL)
+ return NULL;
+
+ loop->refcount = 1;
+
+ return loop;
+}
+
+void
+bus_loop_ref (BusLoop *loop)
+{
+ _dbus_assert (loop != NULL);
+ _dbus_assert (loop->refcount > 0);
+
+ loop->refcount += 1;
+}
+
+void
+bus_loop_unref (BusLoop *loop)
+{
+ _dbus_assert (loop != NULL);
+ _dbus_assert (loop->refcount > 0);
+
+ loop->refcount -= 1;
+ if (loop->refcount == 0)
+ {
+
+ dbus_free (loop);
+ }
}
dbus_bool_t
-bus_loop_add_watch (DBusWatch *watch,
+bus_loop_add_watch (BusLoop *loop,
+ DBusWatch *watch,
BusWatchFunction function,
void *data,
DBusFreeFunction free_data_func)
if (wcb == NULL)
return FALSE;
- if (!add_callback ((Callback*) wcb))
+ if (!add_callback (loop, (Callback*) wcb))
{
wcb->callback.free_data_func = NULL; /* don't want to have this side effect */
callback_free ((Callback*) wcb);
}
void
-bus_loop_remove_watch (DBusWatch *watch,
+bus_loop_remove_watch (BusLoop *loop,
+ DBusWatch *watch,
BusWatchFunction function,
void *data)
{
DBusList *link;
- link = _dbus_list_get_first_link (&callbacks);
+ link = _dbus_list_get_first_link (&loop->callbacks);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&callbacks, link);
+ DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
Callback *this = link->data;
if (this->type == CALLBACK_WATCH &&
this->data == data &&
WATCH_CALLBACK (this)->function == function)
{
- remove_callback (link);
+ remove_callback (loop, link);
return;
}
}
dbus_bool_t
-bus_loop_add_timeout (DBusTimeout *timeout,
+bus_loop_add_timeout (BusLoop *loop,
+ DBusTimeout *timeout,
BusTimeoutFunction function,
void *data,
DBusFreeFunction free_data_func)
if (tcb == NULL)
return FALSE;
- if (!add_callback ((Callback*) tcb))
+ if (!add_callback (loop, (Callback*) tcb))
{
tcb->callback.free_data_func = NULL; /* don't want to have this side effect */
callback_free ((Callback*) tcb);
}
void
-bus_loop_remove_timeout (DBusTimeout *timeout,
+bus_loop_remove_timeout (BusLoop *loop,
+ DBusTimeout *timeout,
BusTimeoutFunction function,
void *data)
{
DBusList *link;
- link = _dbus_list_get_first_link (&callbacks);
+ link = _dbus_list_get_first_link (&loop->callbacks);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&callbacks, link);
+ DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
Callback *this = link->data;
if (this->type == CALLBACK_TIMEOUT &&
this->data == data &&
TIMEOUT_CALLBACK (this)->function == function)
{
- remove_callback (link);
+ remove_callback (loop, link);
return;
}
*/
dbus_bool_t
-bus_loop_iterate (dbus_bool_t block)
+bus_loop_iterate (BusLoop *loop,
+ dbus_bool_t block)
{
dbus_bool_t retval;
DBusPollFD *fds;
int initial_serial;
long timeout;
dbus_bool_t oom_watch_pending;
+ int orig_depth;
retval = FALSE;
fds = NULL;
watches_for_fds = NULL;
oom_watch_pending = FALSE;
-
+ orig_depth = loop->depth;
+
#if 0
_dbus_verbose (" iterate %d timeouts %d watches\n",
- timeout_count, watch_count);
+ loop->timeout_count, loop->watch_count);
#endif
- if (callbacks == NULL)
+ if (loop->callbacks == NULL)
{
- bus_loop_quit ();
+ bus_loop_quit (loop);
goto next_iteration;
}
/* count enabled watches */
n_fds = 0;
- link = _dbus_list_get_first_link (&callbacks);
+ link = _dbus_list_get_first_link (&loop->callbacks);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&callbacks, link);
+ DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
Callback *cb = link->data;
if (cb->type == CALLBACK_WATCH)
{
}
i = 0;
- link = _dbus_list_get_first_link (&callbacks);
+ link = _dbus_list_get_first_link (&loop->callbacks);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&callbacks, link);
+ DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
Callback *cb = link->data;
if (cb->type == CALLBACK_WATCH)
{
}
timeout = -1;
- if (timeout_count > 0)
+ if (loop->timeout_count > 0)
{
unsigned long tv_sec;
unsigned long tv_usec;
_dbus_get_current_time (&tv_sec, &tv_usec);
- link = _dbus_list_get_first_link (&callbacks);
+ link = _dbus_list_get_first_link (&loop->callbacks);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&callbacks, link);
+ DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
Callback *cb = link->data;
if (cb->type == CALLBACK_TIMEOUT &&
n_ready = _dbus_poll (fds, n_fds, timeout);
- initial_serial = callback_list_serial;
+ initial_serial = loop->callback_list_serial;
- if (timeout_count > 0)
+ if (loop->timeout_count > 0)
{
unsigned long tv_sec;
unsigned long tv_usec;
_dbus_get_current_time (&tv_sec, &tv_usec);
/* It'd be nice to avoid this O(n) thingy here */
- link = _dbus_list_get_first_link (&callbacks);
+ link = _dbus_list_get_first_link (&loop->callbacks);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&callbacks, link);
+ DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
Callback *cb = link->data;
- if (initial_serial != callback_list_serial)
+ if (initial_serial != loop->callback_list_serial)
goto next_iteration;
- if (exited)
+ if (loop->depth != orig_depth)
goto next_iteration;
if (cb->type == CALLBACK_TIMEOUT &&
* approach could result in starving watches
* toward the end of the list.
*/
- if (initial_serial != callback_list_serial)
+ if (initial_serial != loop->callback_list_serial)
goto next_iteration;
- if (exited)
+ if (loop->depth != orig_depth)
goto next_iteration;
if (fds[i].revents != 0)
return retval;
}
-
void
-bus_loop_run (void)
+bus_loop_run (BusLoop *loop)
{
- while (!exited)
- bus_loop_iterate (TRUE);
+ int our_exit_depth;
+
+ bus_loop_ref (loop);
+
+ our_exit_depth = loop->depth;
+ loop->depth += 1;
+
+ while (loop->depth != our_exit_depth)
+ bus_loop_iterate (loop, TRUE);
+
+ bus_loop_unref (loop);
}
void
-bus_loop_quit (void)
+bus_loop_quit (BusLoop *loop)
{
- exited = TRUE;
+ _dbus_assert (loop->depth > 0);
+
+ loop->depth -= 1;
}
#include <dbus/dbus.h>
+typedef struct BusLoop BusLoop;
+
typedef dbus_bool_t (* BusWatchFunction) (DBusWatch *watch,
unsigned int condition,
void *data);
typedef void (* BusTimeoutFunction) (DBusTimeout *timeout,
void *data);
-dbus_bool_t bus_loop_add_watch (DBusWatch *watch,
+
+BusLoop* bus_loop_new (void);
+void bus_loop_ref (BusLoop *loop);
+void bus_loop_unref (BusLoop *loop);
+dbus_bool_t bus_loop_add_watch (BusLoop *loop,
+ DBusWatch *watch,
BusWatchFunction function,
void *data,
DBusFreeFunction free_data_func);
-void bus_loop_remove_watch (DBusWatch *watch,
+void bus_loop_remove_watch (BusLoop *loop,
+ DBusWatch *watch,
BusWatchFunction function,
void *data);
-dbus_bool_t bus_loop_add_timeout (DBusTimeout *timeout,
+dbus_bool_t bus_loop_add_timeout (BusLoop *loop,
+ DBusTimeout *timeout,
BusTimeoutFunction function,
void *data,
DBusFreeFunction free_data_func);
-void bus_loop_remove_timeout (DBusTimeout *timeout,
+void bus_loop_remove_timeout (BusLoop *loop,
+ DBusTimeout *timeout,
BusTimeoutFunction function,
void *data);
-void bus_loop_run (void);
-void bus_loop_quit (void);
-dbus_bool_t bus_loop_iterate (dbus_bool_t block);
+void bus_loop_run (BusLoop *loop);
+void bus_loop_quit (BusLoop *loop);
+dbus_bool_t bus_loop_iterate (BusLoop *loop,
+ dbus_bool_t block);
+
#endif /* BUS_LOOP_H */
}
_dbus_verbose ("We are on D-Bus...\n");
- bus_loop_run ();
+ bus_loop_run (bus_context_get_loop (context));
bus_context_shutdown (context);
bus_context_unref (context);
* are different from the real handlers in connection.c
*/
static DBusList *clients = NULL;
+static BusLoop *client_loop = NULL;
static dbus_bool_t
client_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
+ unsigned int condition,
+ void *data)
{
DBusConnection *connection = data;
dbus_bool_t retval;
static dbus_bool_t
add_client_watch (DBusWatch *watch,
- DBusConnection *connection)
+ void *data)
{
- return bus_loop_add_watch (watch, client_watch_callback, connection,
+ DBusConnection *connection = data;
+
+ return bus_loop_add_watch (client_loop,
+ watch, client_watch_callback, connection,
NULL);
}
static void
remove_client_watch (DBusWatch *watch,
- DBusConnection *connection)
+ void *data)
{
- bus_loop_remove_watch (watch, client_watch_callback, connection);
+ DBusConnection *connection = data;
+
+ bus_loop_remove_watch (client_loop,
+ watch, client_watch_callback, connection);
}
static void
client_timeout_callback (DBusTimeout *timeout,
- void *data)
+ void *data)
{
DBusConnection *connection = data;
static dbus_bool_t
add_client_timeout (DBusTimeout *timeout,
- DBusConnection *connection)
+ void *data)
{
- return bus_loop_add_timeout (timeout, client_timeout_callback, connection, NULL);
+ DBusConnection *connection = data;
+
+ return bus_loop_add_timeout (client_loop, timeout, client_timeout_callback, connection, NULL);
}
static void
remove_client_timeout (DBusTimeout *timeout,
- DBusConnection *connection)
+ void *data)
{
- bus_loop_remove_timeout (timeout, client_timeout_callback, connection);
+ DBusConnection *connection = data;
+
+ bus_loop_remove_timeout (client_loop, timeout, client_timeout_callback, connection);
}
static DBusHandlerResult
connection);
_dbus_list_remove (&clients, connection);
-
+
dbus_connection_unref (connection);
+ if (clients == NULL)
+ {
+ bus_loop_unref (client_loop);
+ client_loop = NULL;
+ }
+
return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
}
}
retval = FALSE;
+
+ if (client_loop == NULL)
+ {
+ client_loop = bus_loop_new ();
+ if (client_loop == NULL)
+ goto out;
+ }
if (!dbus_connection_set_watch_functions (connection,
- (DBusAddWatchFunction) add_client_watch,
- (DBusRemoveWatchFunction) remove_client_watch,
+ add_client_watch,
+ remove_client_watch,
NULL,
connection,
NULL))
goto out;
if (!dbus_connection_set_timeout_functions (connection,
- (DBusAddTimeoutFunction) add_client_timeout,
- (DBusRemoveTimeoutFunction) remove_client_timeout,
+ add_client_timeout,
+ remove_client_timeout,
NULL,
connection, NULL))
goto out;
NULL, NULL, NULL, NULL, NULL);
_dbus_list_remove_last (&clients, connection);
+
+ if (clients == NULL)
+ {
+ bus_loop_unref (client_loop);
+ client_loop = NULL;
+ }
}
return retval;
}
void
-bus_test_flush_bus (BusContext *context)
+bus_test_run_clients_loop (void)
{
- /* This is race condition city, obviously. since we're all in one
- * process we can't block, we just have to wait for data we put in
- * one end of the debug pipe to come out the other end...
- * a more robust setup would be good. Blocking on the other
- * end of pipes we've pushed data into or something.
- * A simple hack might be to just make the debug server always
- * poll for read on the other end of the pipe after writing.
- */
- while (bus_loop_iterate (FALSE))
+ if (client_loop == NULL)
+ return;
+
+ /* Do one blocking wait, since we're expecting data */
+ bus_loop_iterate (client_loop, TRUE);
+
+ /* Then mop everything up */
+ while (bus_loop_iterate (client_loop, FALSE))
;
-#if 0
- _dbus_sleep_milliseconds (15);
-#endif
- while (bus_loop_iterate (FALSE))
+}
+
+void
+bus_test_run_bus_loop (BusContext *context)
+{
+ /* Do one blocking wait, since we're expecting data */
+ bus_loop_iterate (bus_context_get_loop (context), TRUE);
+
+ /* Then mop everything up */
+ while (bus_loop_iterate (bus_context_get_loop (context), FALSE))
;
}
+void
+bus_test_run_everything (BusContext *context)
+{
+ int i;
+
+ i = 0;
+ while (i < 2)
+ {
+ while (bus_loop_iterate (bus_context_get_loop (context), FALSE) ||
+ (client_loop == NULL || bus_loop_iterate (client_loop, FALSE)))
+ ;
+ ++i;
+ }
+}
+
BusContext*
bus_context_new_test (const DBusString *test_data_dir,
const char *filename)
#include <dbus/dbus-string.h>
#include "connection.h"
-dbus_bool_t bus_dispatch_test (const DBusString *test_data_dir);
-dbus_bool_t bus_policy_test (const DBusString *test_data_dir);
-dbus_bool_t bus_config_parser_test (const DBusString *test_data_dir);
-dbus_bool_t bus_setup_debug_client (DBusConnection *connection);
-void bus_test_clients_foreach (BusConnectionForeachFunction function,
- void *data);
-dbus_bool_t bus_test_client_listed (DBusConnection *connection);
-void bus_test_flush_bus (BusContext *context);
-
-BusContext* bus_context_new_test (const DBusString *test_data_dir,
- const char *filename);
+dbus_bool_t bus_dispatch_test (const DBusString *test_data_dir);
+dbus_bool_t bus_policy_test (const DBusString *test_data_dir);
+dbus_bool_t bus_config_parser_test (const DBusString *test_data_dir);
+dbus_bool_t bus_setup_debug_client (DBusConnection *connection);
+void bus_test_clients_foreach (BusConnectionForeachFunction function,
+ void *data);
+dbus_bool_t bus_test_client_listed (DBusConnection *connection);
+void bus_test_run_bus_loop (BusContext *context);
+void bus_test_run_clients_loop (void);
+void bus_test_run_everything (BusContext *context);
+BusContext* bus_context_new_test (const DBusString *test_data_dir,
+ const char *filename);
+
#endif
to return an error that automatically gets turned into a message; most likely
some basic spec'ing out of the GLib/Qt level stubs/skels stuff will be
needed to understand the right approach.
+
+ - sync up DBusWatch and DBusTimeout so that handle_watch() is a method on DBusWatch
+ similar to the way timeouts work
+
+ - there are various bits of code to manage ref/unref of data slots, that should
+ be merged into a generic facility