Commit 1b080361 authored by Havoc Pennington's avatar Havoc Pennington

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
parent f216e814
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
......
......@@ -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,
......
......@@ -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,
......
......@@ -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;
......
......@@ -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);
......
This diff is collapsed.
......@@ -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 */
......@@ -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);
......
......@@ -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))
;