summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2003-04-04 00:39:22 +0000
committerHavoc Pennington <hp@redhat.com>2003-04-04 00:39:22 +0000
commit1b08036103a70159e7a67b2349306710edcd6654 (patch)
tree6c6469bc51f9abcd2cf69036aabc71dea75c03b2
parentf216e81432ddf04889202c33a6e68113f94d7611 (diff)
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
-rw-r--r--ChangeLog7
-rw-r--r--bus/bus.c154
-rw-r--r--bus/bus.h3
-rw-r--r--bus/connection.c58
-rw-r--r--bus/dispatch.c127
-rw-r--r--bus/loop.c166
-rw-r--r--bus/loop.h26
-rw-r--r--bus/main.c2
-rw-r--r--bus/test.c110
-rw-r--r--bus/test.h24
-rw-r--r--doc/TODO6
11 files changed, 551 insertions, 132 deletions
diff --git a/ChangeLog b/ChangeLog
index a164df07..363fc3ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
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
diff --git a/bus/bus.c b/bus/bus.c
index 381f6317..9125fc75 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -38,6 +38,7 @@ struct BusContext
int refcount;
char *type;
char *address;
+ BusLoop *loop;
DBusList *servers;
BusConnections *connections;
BusActivation *activation;
@@ -48,6 +49,68 @@ struct BusContext
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,
@@ -62,7 +125,13 @@ static dbus_bool_t
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);
}
@@ -70,7 +139,13 @@ static void
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);
}
@@ -86,14 +161,26 @@ static dbus_bool_t
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
@@ -139,12 +226,22 @@ free_rule_list_func (void *data)
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);
@@ -175,7 +272,18 @@ setup_server (BusContext *context,
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;
}
@@ -196,8 +304,18 @@ bus_context_new (const DBusString *config_file,
_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;
@@ -215,6 +333,13 @@ bus_context_new (const DBusString *config_file,
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);
@@ -401,6 +526,9 @@ bus_context_new (const DBusString *config_file,
_dbus_string_free (&full_address);
dbus_free_string_array (auth_mechanisms);
+
+ server_data_slot_unref ();
+
return NULL;
}
@@ -501,9 +629,17 @@ bus_context_unref (BusContext *context)
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 ();
}
}
@@ -532,6 +668,12 @@ bus_context_get_activation (BusContext *context)
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,
diff --git a/bus/bus.h b/bus/bus.h
index 902f5fac..8357f7b8 100644
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -29,6 +29,8 @@
#include <dbus/dbus.h>
#include <dbus/dbus-string.h>
+#include "loop.h"
+
typedef struct BusActivation BusActivation;
typedef struct BusConnections BusConnections;
typedef struct BusContext BusContext;
@@ -47,6 +49,7 @@ const char* bus_context_get_type (BusContext *context)
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,
diff --git a/bus/connection.c b/bus/connection.c
index 3c43200f..aa8d65ca 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -89,6 +89,16 @@ connection_data_slot_unref (void)
}
}
+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)
{
@@ -195,17 +205,23 @@ connection_watch_callback (DBusWatch *watch,
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
@@ -226,16 +242,22 @@ connection_timeout_callback (DBusTimeout *timeout,
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
@@ -366,16 +388,16 @@ bus_connections_setup_connection (BusConnections *connections,
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;
@@ -400,12 +422,7 @@ bus_connections_setup_connection (BusConnections *connections,
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,
@@ -420,6 +437,11 @@ bus_connections_setup_connection (BusConnections *connections,
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;
diff --git a/bus/dispatch.c b/bus/dispatch.c
index 7c65ac42..21d57ae1 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -537,8 +537,8 @@ kill_client_connection (BusContext *context,
/* 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 */
@@ -729,8 +729,8 @@ check_hello_message (BusContext *context,
dbus_message_unref (message);
message = NULL;
-
- bus_test_flush_bus (context);
+
+ bus_test_run_everything (context);
if (!dbus_connection_get_is_connected (connection))
{
@@ -963,8 +963,8 @@ check_nonexistent_service_activation (BusContext *context,
dbus_message_unref (message);
message = NULL;
-
- bus_test_flush_bus (context);
+
+ bus_test_run_everything (context);
if (!dbus_connection_get_is_connected (connection))
{
@@ -1028,6 +1028,116 @@ check_nonexistent_service_activation (BusContext *context,
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;
@@ -1153,6 +1263,11 @@ bus_dispatch_test (const DBusString *test_data_dir)
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);
diff --git a/bus/loop.c b/bus/loop.c
index 93096dc5..a237defa 100644
--- a/bus/loop.c
+++ b/bus/loop.c
@@ -26,11 +26,15 @@
#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
{
@@ -121,20 +125,21 @@ callback_free (Callback *cb)
}
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;
}
@@ -142,27 +147,66 @@ add_callback (Callback *cb)
}
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)
@@ -173,7 +217,7 @@ bus_loop_add_watch (DBusWatch *watch,
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);
@@ -184,16 +228,17 @@ bus_loop_add_watch (DBusWatch *watch,
}
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 &&
@@ -201,7 +246,7 @@ bus_loop_remove_watch (DBusWatch *watch,
this->data == data &&
WATCH_CALLBACK (this)->function == function)
{
- remove_callback (link);
+ remove_callback (loop, link);
return;
}
@@ -214,7 +259,8 @@ bus_loop_remove_watch (DBusWatch *watch,
}
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)
@@ -225,7 +271,7 @@ bus_loop_add_timeout (DBusTimeout *timeout,
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);
@@ -236,16 +282,17 @@ bus_loop_add_timeout (DBusTimeout *timeout,
}
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 &&
@@ -253,7 +300,7 @@ bus_loop_remove_timeout (DBusTimeout *timeout,
this->data == data &&
TIMEOUT_CALLBACK (this)->function == function)
{
- remove_callback (link);
+ remove_callback (loop, link);
return;
}
@@ -270,7 +317,8 @@ bus_loop_remove_timeout (DBusTimeout *timeout,
*/
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;
@@ -282,30 +330,32 @@ bus_loop_iterate (dbus_bool_t block)
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)
{
@@ -337,10 +387,10 @@ bus_loop_iterate (dbus_bool_t block)
}
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)
{
@@ -378,7 +428,7 @@ bus_loop_iterate (dbus_bool_t block)
}
timeout = -1;
- if (timeout_count > 0)
+ if (loop->timeout_count > 0)
{
unsigned long tv_sec;
unsigned long tv_usec;
@@ -387,10 +437,10 @@ bus_loop_iterate (dbus_bool_t block)
_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 &&
@@ -446,9 +496,9 @@ bus_loop_iterate (dbus_bool_t block)
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;
@@ -456,16 +506,16 @@ bus_loop_iterate (dbus_bool_t block)
_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 &&
@@ -528,10 +578,10 @@ bus_loop_iterate (dbus_bool_t block)
* 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)
@@ -578,16 +628,26 @@ bus_loop_iterate (dbus_bool_t block)
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;
}
diff --git a/bus/loop.h b/bus/loop.h
index b217a776..19b3bcd4 100644
--- a/bus/loop.h
+++ b/bus/loop.h
@@ -26,28 +26,40 @@
#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 */
diff --git a/bus/main.c b/bus/main.c
index fcde3493..099219c3 100644
--- a/bus/main.c
+++ b/bus/main.c
@@ -143,7 +143,7 @@ main (int argc, char **argv)
}
_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);
diff --git a/bus/test.c b/bus/test.c
index d6697085..00a522c6 100644
--- a/bus/test.c
+++ b/bus/test.c
@@ -34,11 +34,12 @@
* 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;
@@ -54,22 +55,28 @@ client_watch_callback (DBusWatch *watch,
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;
@@ -83,16 +90,20 @@ client_timeout_callback (DBusTimeout *timeout,
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
@@ -105,9 +116,15 @@ client_disconnect_handler (DBusMessageHandler *handler,
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;
}
@@ -179,18 +196,25 @@ bus_setup_debug_client (DBusConnection *connection)
}
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;
@@ -223,6 +247,12 @@ bus_setup_debug_client (DBusConnection *connection)
NULL, NULL, NULL, NULL, NULL);
_dbus_list_remove_last (&clients, connection);
+
+ if (clients == NULL)
+ {
+ bus_loop_unref (client_loop);
+ client_loop = NULL;
+ }
}
return retval;
@@ -268,25 +298,45 @@ bus_test_client_listed (DBusConnection *connection)
}
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)
diff --git a/bus/test.h b/bus/test.h
index d8ab67b8..5606bb99 100644
--- a/bus/test.h
+++ b/bus/test.h
@@ -32,17 +32,19 @@
#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
diff --git a/doc/TODO b/doc/TODO
index f6c539dd..c4e3e830 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -59,3 +59,9 @@
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