2003-03-13 Havoc Pennington <hp@redhat.com>

* dbus/dbus-timeout.c (_dbus_timeout_list_set_functions): handle
	out of memory

	* dbus/dbus-watch.c (_dbus_watch_list_set_functions): handle out
	of memory

	* dbus/dbus-connection.h: Make AddWatchFunction and
	AddTimeoutFunction return a bool so they can fail on out-of-memory

	* bus/bus.c (bus_context_new): set up timeout handlers

	* bus/connection.c (bus_connections_setup_connection): set up
	timeout handlers

	* glib/dbus-gmain.c: adapt to the fact that set_functions stuff
	can fail

	* bus/bus.c (bus_context_new): adapt to changes

	* bus/connection.c: adapt to changes

	* test/watch.c: adapt to DBusWatch changes

	* bus/dispatch.c (bus_dispatch_test): started adding this but
	didn't finish
This commit is contained in:
Havoc Pennington 2003-03-14 01:27:58 +00:00
parent 81c30364c2
commit 3bea935316
19 changed files with 866 additions and 229 deletions

View file

@ -1,3 +1,31 @@
2003-03-13 Havoc Pennington <hp@redhat.com>
* dbus/dbus-timeout.c (_dbus_timeout_list_set_functions): handle
out of memory
* dbus/dbus-watch.c (_dbus_watch_list_set_functions): handle out
of memory
* dbus/dbus-connection.h: Make AddWatchFunction and
AddTimeoutFunction return a bool so they can fail on out-of-memory
* bus/bus.c (bus_context_new): set up timeout handlers
* bus/connection.c (bus_connections_setup_connection): set up
timeout handlers
* glib/dbus-gmain.c: adapt to the fact that set_functions stuff
can fail
* bus/bus.c (bus_context_new): adapt to changes
* bus/connection.c: adapt to changes
* test/watch.c: adapt to DBusWatch changes
* bus/dispatch.c (bus_dispatch_test): started adding this but
didn't finish
2003-03-14 Anders Carlsson <andersca@codefactory.se>
* bus/dispatch.c (send_service_nonexistent_error): Fix typo.

View file

@ -60,7 +60,7 @@ noinst_PROGRAMS=$(TESTS)
bus_test_SOURCES= \
test-main.c
bus_test_LDADD= $(top_builddir)/dbus/libdbus-convenience.la libdbus-daemon.la
bus_test_LDADD= $(top_builddir)/dbus/libdbus-1.la libdbus-daemon.la
## mop up the gcov files
clean-local:

View file

@ -49,12 +49,12 @@ server_watch_callback (DBusWatch *watch,
dbus_server_handle_watch (context->server, watch, condition);
}
static void
static dbus_bool_t
add_server_watch (DBusWatch *watch,
BusContext *context)
{
bus_loop_add_watch (watch, server_watch_callback, context,
NULL);
return bus_loop_add_watch (watch, server_watch_callback, context,
NULL);
}
static void
@ -64,6 +64,27 @@ remove_server_watch (DBusWatch *watch,
bus_loop_remove_watch (watch, server_watch_callback, context);
}
static void
server_timeout_callback (DBusTimeout *timeout,
void *data)
{
dbus_timeout_handle (timeout);
}
static dbus_bool_t
add_server_timeout (DBusTimeout *timeout,
BusContext *context)
{
return bus_loop_add_timeout (timeout, server_timeout_callback, context, NULL);
}
static void
remove_server_timeout (DBusTimeout *timeout,
BusContext *context)
{
bus_loop_remove_timeout (timeout, server_timeout_callback, context);
}
static void
new_connection_callback (DBusServer *server,
DBusConnection *new_connection,
@ -136,11 +157,24 @@ bus_context_new (const char *address,
new_connection_callback,
context, NULL);
dbus_server_set_watch_functions (context->server,
(DBusAddWatchFunction) add_server_watch,
(DBusRemoveWatchFunction) remove_server_watch,
context,
NULL);
if (!dbus_server_set_watch_functions (context->server,
(DBusAddWatchFunction) add_server_watch,
(DBusRemoveWatchFunction) remove_server_watch,
context,
NULL))
{
BUS_SET_OOM (error);
goto failed;
}
if (!dbus_server_set_timeout_functions (context->server,
(DBusAddTimeoutFunction) add_server_timeout,
(DBusRemoveTimeoutFunction) remove_server_timeout,
context, NULL))
{
BUS_SET_OOM (error);
goto failed;
}
return context;
@ -152,6 +186,22 @@ bus_context_new (const char *address,
void
bus_context_shutdown (BusContext *context)
{
if (context->server == NULL ||
!dbus_server_get_is_connected (context->server))
return;
if (!dbus_server_set_watch_functions (context->server,
NULL, NULL,
context,
NULL))
_dbus_assert_not_reached ("setting watch functions to NULL failed");
if (!dbus_server_set_timeout_functions (context->server,
NULL, NULL,
context,
NULL))
_dbus_assert_not_reached ("setting timeout functions to NULL failed");
dbus_server_disconnect (context->server);
}
@ -170,6 +220,8 @@ bus_context_unref (BusContext *context)
if (context->refcount == 0)
{
bus_context_shutdown (context);
if (context->registry)
bus_registry_unref (context->registry);
if (context->connections)

View file

@ -108,11 +108,18 @@ bus_connection_disconnected (DBusConnection *connection)
bus_dispatch_remove_connection (connection);
/* no more watching */
dbus_connection_set_watch_functions (connection,
NULL, NULL,
connection,
NULL);
if (!dbus_connection_set_watch_functions (connection,
NULL, NULL,
connection,
NULL))
_dbus_assert_not_reached ("setting watch functions to NULL failed");
if (!dbus_connection_set_timeout_functions (connection,
NULL, NULL,
connection,
NULL))
_dbus_assert_not_reached ("setting timeout functions to NULL failed");
bus_connection_remove_transactions (connection);
_dbus_list_remove (&d->connections->list, connection);
@ -140,12 +147,12 @@ connection_watch_callback (DBusWatch *watch,
dbus_connection_unref (connection);
}
static void
static dbus_bool_t
add_connection_watch (DBusWatch *watch,
DBusConnection *connection)
{
bus_loop_add_watch (watch, connection_watch_callback, connection,
NULL);
return bus_loop_add_watch (watch, connection_watch_callback, connection,
NULL);
}
static void
@ -155,6 +162,27 @@ remove_connection_watch (DBusWatch *watch,
bus_loop_remove_watch (watch, connection_watch_callback, connection);
}
static void
connection_timeout_callback (DBusTimeout *timeout,
void *data)
{
dbus_timeout_handle (timeout);
}
static dbus_bool_t
add_connection_timeout (DBusTimeout *timeout,
DBusConnection *connection)
{
return bus_loop_add_timeout (timeout, connection_timeout_callback, connection, NULL);
}
static void
remove_connection_timeout (DBusTimeout *timeout,
DBusConnection *connection)
{
bus_loop_remove_timeout (timeout, connection_timeout_callback, connection);
}
static void
free_connection_data (void *data)
{
@ -249,18 +277,35 @@ bus_connections_setup_connection (BusConnections *connections,
dbus_connection_disconnect (connection);
return FALSE;
}
dbus_connection_ref (connection);
dbus_connection_set_watch_functions (connection,
(DBusAddWatchFunction) add_connection_watch,
(DBusRemoveWatchFunction) remove_connection_watch,
connection,
NULL);
if (!dbus_connection_set_watch_functions (connection,
(DBusAddWatchFunction) add_connection_watch,
(DBusRemoveWatchFunction) remove_connection_watch,
connection,
NULL))
{
dbus_connection_disconnect (connection);
return FALSE;
}
if (!dbus_connection_set_timeout_functions (connection,
(DBusAddTimeoutFunction) add_connection_timeout,
(DBusRemoveTimeoutFunction) remove_connection_timeout,
connection, NULL))
{
dbus_connection_disconnect (connection);
return FALSE;
}
/* Setup the connection with the dispatcher */
if (!bus_dispatch_add_connection (connection))
return FALSE;
{
dbus_connection_disconnect (connection);
return FALSE;
}
dbus_connection_ref (connection);
return TRUE;
}

View file

@ -27,6 +27,7 @@
#include "services.h"
#include "utils.h"
#include "bus.h"
#include "test.h"
#include <dbus/dbus-internals.h>
#include <string.h>
@ -142,11 +143,9 @@ send_service_nonexistent_error (BusTransaction *transaction,
return TRUE;
}
static DBusHandlerResult
bus_dispatch_message_handler (DBusMessageHandler *handler,
DBusConnection *connection,
DBusMessage *message,
void *user_data)
static void
bus_dispatch (DBusConnection *connection,
DBusMessage *message)
{
const char *sender, *service_name, *message_name;
DBusError error;
@ -313,6 +312,15 @@ bus_dispatch_message_handler (DBusMessageHandler *handler,
}
dbus_connection_unref (connection);
}
static DBusHandlerResult
bus_dispatch_message_handler (DBusMessageHandler *handler,
DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
bus_dispatch (connection, message);
return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
}
@ -361,3 +369,70 @@ bus_dispatch_remove_connection (DBusConnection *connection)
NULL, NULL);
}
#ifdef DBUS_BUILD_TESTS
static void
run_test_bus (BusContext *context)
{
}
static dbus_bool_t
check_hello_message (BusContext *context,
DBusConnection *connection)
{
DBusMessage *message;
dbus_int32_t serial;
message = dbus_message_new (DBUS_SERVICE_DBUS,
DBUS_MESSAGE_HELLO);
if (message == NULL)
_dbus_assert_not_reached ("no memory");
if (!dbus_connection_send (connection, message, &serial))
_dbus_assert_not_reached ("no memory");
return TRUE;
}
dbus_bool_t
bus_dispatch_test (const DBusString *test_data_dir)
{
BusContext *context;
DBusError error;
const char *activation_dirs[] = { NULL, NULL };
DBusConnection *foo;
DBusConnection *bar;
DBusConnection *baz;
DBusResultCode result;
return TRUE; /* FIXME */
dbus_error_init (&error);
context = bus_context_new ("debug:name=test-server",
activation_dirs,
&error);
if (context == NULL)
_dbus_assert_not_reached ("could not alloc context");
foo = dbus_connection_open ("debug:name=test-server", &result);
if (foo == NULL)
_dbus_assert_not_reached ("could not alloc connection");
bar = dbus_connection_open ("debug:name=test-server", &result);
if (bar == NULL)
_dbus_assert_not_reached ("could not alloc connection");
baz = dbus_connection_open ("debug:name=test-server", &result);
if (baz == NULL)
_dbus_assert_not_reached ("could not alloc connection");
return TRUE;
}
#endif /* DBUS_BUILD_TESTS */

View file

@ -26,20 +26,46 @@
#include <dbus/dbus-list.h>
#include <dbus/dbus-sysdeps.h>
static DBusList *watches = NULL;
static int watch_list_serial = 0;
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;
typedef enum
{
CALLBACK_WATCH,
CALLBACK_TIMEOUT
} CallbackType;
typedef struct
{
DBusWatch *watch;
BusWatchFunction function;
CallbackType type;
void *data;
DBusFreeFunction free_data_func;
} Callback;
typedef struct
{
Callback callback;
BusWatchFunction function;
DBusWatch *watch;
} WatchCallback;
dbus_bool_t
bus_loop_add_watch (DBusWatch *watch,
typedef struct
{
Callback callback;
DBusTimeout *timeout;
BusTimeoutFunction function;
unsigned long last_tv_sec;
unsigned long last_tv_usec;
} TimeoutCallback;
#define WATCH_CALLBACK(callback) ((WatchCallback*)callback)
#define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback)
static WatchCallback*
watch_callback_new (DBusWatch *watch,
BusWatchFunction function,
void *data,
DBusFreeFunction free_data_func)
@ -48,20 +74,108 @@ bus_loop_add_watch (DBusWatch *watch,
cb = dbus_new (WatchCallback, 1);
if (cb == NULL)
return FALSE;
return NULL;
cb->watch = watch;
cb->function = function;
cb->data = data;
cb->free_data_func = free_data_func;
cb->callback.type = CALLBACK_WATCH;
cb->callback.data = data;
cb->callback.free_data_func = free_data_func;
if (!_dbus_list_append (&watches, cb))
return cb;
}
static TimeoutCallback*
timeout_callback_new (DBusTimeout *timeout,
BusTimeoutFunction function,
void *data,
DBusFreeFunction free_data_func)
{
TimeoutCallback *cb;
cb = dbus_new (TimeoutCallback, 1);
if (cb == NULL)
return NULL;
cb->timeout = timeout;
cb->function = function;
_dbus_get_current_time (&cb->last_tv_sec,
&cb->last_tv_usec);
cb->callback.type = CALLBACK_TIMEOUT;
cb->callback.data = data;
cb->callback.free_data_func = free_data_func;
return cb;
}
static void
callback_free (Callback *cb)
{
if (cb->free_data_func)
(* cb->free_data_func) (cb->data);
dbus_free (cb);
}
static dbus_bool_t
add_callback (Callback *cb)
{
if (!_dbus_list_append (&callbacks, cb))
return FALSE;
callback_list_serial += 1;
switch (cb->type)
{
dbus_free (cb);
case CALLBACK_WATCH:
watch_count += 1;
break;
case CALLBACK_TIMEOUT:
timeout_count += 1;
break;
}
return TRUE;
}
static void
remove_callback (DBusList *link)
{
Callback *cb = link->data;
switch (cb->type)
{
case CALLBACK_WATCH:
watch_count -= 1;
break;
case CALLBACK_TIMEOUT:
timeout_count -= 1;
break;
}
callback_free (cb);
_dbus_list_remove_link (&callbacks, link);
callback_list_serial += 1;
}
dbus_bool_t
bus_loop_add_watch (DBusWatch *watch,
BusWatchFunction function,
void *data,
DBusFreeFunction free_data_func)
{
WatchCallback *wcb;
wcb = watch_callback_new (watch, function, data, free_data_func);
if (wcb == NULL)
return FALSE;
if (!add_callback ((Callback*) wcb))
{
wcb->callback.free_data_func = NULL; /* don't want to have this side effect */
callback_free ((Callback*) wcb);
return FALSE;
}
watch_list_serial += 1;
return TRUE;
}
@ -73,23 +187,18 @@ bus_loop_remove_watch (DBusWatch *watch,
{
DBusList *link;
link = _dbus_list_get_first_link (&watches);
link = _dbus_list_get_first_link (&callbacks);
while (link != NULL)
{
DBusList *next = _dbus_list_get_next_link (&watches, link);
WatchCallback *cb = link->data;
DBusList *next = _dbus_list_get_next_link (&callbacks, link);
Callback *this = link->data;
if (cb->watch == watch &&
cb->function == function &&
cb->data == data)
if (this->type == CALLBACK_WATCH &&
WATCH_CALLBACK (this)->watch == watch &&
this->data == data &&
WATCH_CALLBACK (this)->function == function)
{
_dbus_list_remove_link (&watches, link);
watch_list_serial += 1;
if (cb->free_data_func)
(* cb->free_data_func) (cb->data);
dbus_free (cb);
remove_callback (link);
return;
}
@ -101,6 +210,58 @@ bus_loop_remove_watch (DBusWatch *watch,
watch, function, data);
}
dbus_bool_t
bus_loop_add_timeout (DBusTimeout *timeout,
BusTimeoutFunction function,
void *data,
DBusFreeFunction free_data_func)
{
TimeoutCallback *tcb;
tcb = timeout_callback_new (timeout, function, data, free_data_func);
if (tcb == NULL)
return FALSE;
if (!add_callback ((Callback*) tcb))
{
tcb->callback.free_data_func = NULL; /* don't want to have this side effect */
callback_free ((Callback*) tcb);
return FALSE;
}
return TRUE;
}
void
bus_loop_remove_timeout (DBusTimeout *timeout,
BusTimeoutFunction function,
void *data)
{
DBusList *link;
link = _dbus_list_get_first_link (&callbacks);
while (link != NULL)
{
DBusList *next = _dbus_list_get_next_link (&callbacks, link);
Callback *this = link->data;
if (this->type == CALLBACK_TIMEOUT &&
TIMEOUT_CALLBACK (this)->timeout == timeout &&
this->data == data &&
TIMEOUT_CALLBACK (this)->function == function)
{
remove_callback (link);
return;
}
link = next;
}
_dbus_warn ("could not find timeout %p function %p data %p to remove\n",
timeout, function, data);
}
void
bus_loop_run (void)
{
@ -113,59 +274,187 @@ bus_loop_run (void)
DBusList *link;
int n_ready;
int initial_serial;
long timeout;
fds = NULL;
watches_for_fds = NULL;
n_fds = _dbus_list_get_length (&watches);
if (n_fds == 0)
if (callbacks == NULL)
{
bus_loop_quit ();
goto next_iteration;
}
fds = dbus_new0 (DBusPollFD, n_fds);
while (fds == NULL)
n_fds = watch_count;
if (n_fds > 0)
{
bus_wait_for_memory ();
fds = dbus_new0 (DBusPollFD, n_fds);
while (fds == NULL)
{
bus_wait_for_memory ();
fds = dbus_new0 (DBusPollFD, n_fds);
}
watches_for_fds = dbus_new (WatchCallback*, n_fds);
while (watches_for_fds == NULL)
{
bus_wait_for_memory ();
watches_for_fds = dbus_new (WatchCallback*, n_fds);
}
i = 0;
link = _dbus_list_get_first_link (&callbacks);
while (link != NULL)
{
DBusList *next = _dbus_list_get_next_link (&callbacks, link);
Callback *cb = link->data;
if (cb->type == CALLBACK_WATCH)
{
unsigned int flags;
WatchCallback *wcb = WATCH_CALLBACK (cb);
watches_for_fds[i] = wcb;
flags = dbus_watch_get_flags (wcb->watch);
fds[i].fd = dbus_watch_get_fd (wcb->watch);
if (flags & DBUS_WATCH_READABLE)
fds[i].events |= _DBUS_POLLIN;
if (flags & DBUS_WATCH_WRITABLE)
fds[i].events |= _DBUS_POLLOUT;
++i;
}
link = next;
}
_dbus_assert (i == n_fds);
}
watches_for_fds = dbus_new (WatchCallback*, n_fds);
while (watches_for_fds == NULL)
timeout = -1;
if (timeout_count > 0)
{
bus_wait_for_memory ();
watches_for_fds = dbus_new (WatchCallback*, n_fds);
unsigned long tv_sec;
unsigned long tv_usec;
_dbus_get_current_time (&tv_sec, &tv_usec);
link = _dbus_list_get_first_link (&callbacks);
while (link != NULL)
{
DBusList *next = _dbus_list_get_next_link (&callbacks, link);
Callback *cb = link->data;
if (cb->type == CALLBACK_TIMEOUT)
{
TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb);
unsigned long interval;
unsigned long elapsed;
if (tcb->last_tv_sec > tv_sec ||
(tcb->last_tv_sec == tv_sec &&
tcb->last_tv_usec > tv_usec))
{
/* Clock went backward, pretend timeout
* was just installed.
*/
tcb->last_tv_sec = tv_sec;
tcb->last_tv_usec = tv_usec;
_dbus_verbose ("System clock went backward\n");
}
interval = dbus_timeout_get_interval (tcb->timeout);
elapsed =
(tv_sec - tcb->last_tv_sec) * 1000 +
(tv_usec - tcb->last_tv_usec) / 1000;
if (interval < elapsed)
timeout = 0;
else if (timeout < 0)
timeout = interval - elapsed;
else
timeout = MIN (((unsigned long)timeout), interval - elapsed);
_dbus_assert (timeout >= 0);
if (timeout == 0)
break; /* it's not going to get shorter... */
}
link = next;
}
}
i = 0;
link = _dbus_list_get_first_link (&watches);
while (link != NULL)
n_ready = _dbus_poll (fds, n_fds, timeout);
initial_serial = callback_list_serial;
if (timeout_count > 0)
{
DBusList *next = _dbus_list_get_next_link (&watches, link);
WatchCallback *cb = link->data;
int flags;
watches_for_fds[i] = cb;
unsigned long tv_sec;
unsigned long tv_usec;
flags = dbus_watch_get_flags (cb->watch);
fds[i].fd = dbus_watch_get_fd (cb->watch);
if (flags & DBUS_WATCH_READABLE)
fds[i].events |= _DBUS_POLLIN;
if (flags & DBUS_WATCH_WRITABLE)
fds[i].events |= _DBUS_POLLOUT;
link = next;
++i;
_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);
while (link != NULL)
{
DBusList *next = _dbus_list_get_next_link (&callbacks, link);
Callback *cb = link->data;
if (initial_serial != callback_list_serial)
goto next_iteration;
if (exited)
goto next_iteration;
if (cb->type == CALLBACK_TIMEOUT)
{
TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb);
unsigned long interval;
unsigned long elapsed;
if (tcb->last_tv_sec > tv_sec ||
(tcb->last_tv_sec == tv_sec &&
tcb->last_tv_usec > tv_usec))
{
/* Clock went backward, pretend timeout
* was just installed.
*/
tcb->last_tv_sec = tv_sec;
tcb->last_tv_usec = tv_usec;
_dbus_verbose ("System clock went backward\n");
goto next_timeout;
}
interval = dbus_timeout_get_interval (tcb->timeout);
elapsed =
(tv_sec - tcb->last_tv_sec) * 1000 +
(tv_usec - tcb->last_tv_usec) / 1000;
if (interval <= elapsed)
{
/* Save last callback time and fire this timeout */
tcb->last_tv_sec = tv_sec;
tcb->last_tv_usec = tv_usec;
(* tcb->function) (tcb->timeout,
cb->data);
}
}
next_timeout:
link = next;
}
}
n_ready = _dbus_poll (fds, n_fds, -1);
if (n_ready > 0)
{
initial_serial = watch_list_serial;
i = 0;
while (i < n_fds)
{
@ -173,7 +462,7 @@ bus_loop_run (void)
* approach could result in starving watches
* toward the end of the list.
*/
if (initial_serial != watch_list_serial)
if (initial_serial != callback_list_serial)
goto next_iteration;
if (exited)
@ -181,10 +470,10 @@ bus_loop_run (void)
if (fds[i].revents != 0)
{
WatchCallback *cb;
WatchCallback *wcb;
unsigned int condition;
cb = watches_for_fds[i];
wcb = watches_for_fds[i];
condition = 0;
if (fds[i].revents & _DBUS_POLLIN)
@ -201,9 +490,9 @@ bus_loop_run (void)
*/
if (condition != 0)
(* cb->function) (cb->watch,
condition,
cb->data);
(* wcb->function) (wcb->watch,
condition,
((Callback*)wcb)->data);
}
++i;

View file

@ -26,19 +26,29 @@
#include <dbus/dbus.h>
typedef void (* BusWatchFunction) (DBusWatch *watch,
unsigned int condition,
void *data);
typedef void (* BusWatchFunction) (DBusWatch *watch,
unsigned int condition,
void *data);
typedef void (* BusTimeoutFunction) (DBusTimeout *timeout,
void *data);
dbus_bool_t bus_loop_add_watch (DBusWatch *watch,
BusWatchFunction function,
void *data,
DBusFreeFunction free_data_func);
void bus_loop_remove_watch (DBusWatch *watch,
BusWatchFunction function,
void *data);
dbus_bool_t bus_loop_add_timeout (DBusTimeout *timeout,
BusTimeoutFunction function,
void *data,
DBusFreeFunction free_data_func);
void bus_loop_remove_timeout (DBusTimeout *timeout,
BusTimeoutFunction function,
void *data);
void bus_loop_run (void);
void bus_loop_quit (void);
dbus_bool_t bus_loop_add_watch (DBusWatch *watch,
BusWatchFunction function,
void *data,
DBusFreeFunction free_data_func);
void bus_loop_remove_watch (DBusWatch *watch,
BusWatchFunction function,
void *data);
void bus_loop_run (void);
void bus_loop_quit (void);
#endif /* BUS_LOOP_H */

View file

@ -22,16 +22,41 @@
*/
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
#include <dbus/dbus-string.h>
#include <dbus/dbus-sysdeps.h>
static void
die (const char *failure)
{
fprintf (stderr, "Unit test failed: %s\n", failure);
exit (1);
}
int
main (int argc, char **argv)
{
#ifdef DBUS_BUILD_TESTS
const char *dir;
DBusString test_data_dir;
if (argc > 1)
dir = argv[1];
else
dir = _dbus_getenv ("DBUS_TEST_DATA");
if (dir == NULL)
dir = "";
_dbus_string_init_const (&test_data_dir, dir);
if (!bus_dispatch_test (&test_data_dir))
die ("dispatch");
return 0;
#else /* DBUS_BUILD_TESTS */
return 0;
#endif
}

View file

@ -31,7 +31,7 @@
#include <dbus/dbus.h>
#include <dbus/dbus-string.h>
dbus_bool_t bus_test_foo (const DBusString *test_data_dir);
dbus_bool_t bus_dispatch_test (const DBusString *test_data_dir);
#endif

View file

@ -1810,31 +1810,44 @@ dbus_connection_dispatch_message (DBusConnection *connection)
*
* It is not allowed to reference a DBusWatch after it has been passed
* to remove_function.
*
* If #FALSE is returned due to lack of memory, the failure may be due
* to a #FALSE return from the new add_function. If so, the
* add_function may have been called successfully one or more times,
* but the remove_function will also have been called to remove any
* successful adds. i.e. if #FALSE is returned the net result
* should be that dbus_connection_set_watch_functions() has no effect,
* but the add_function and remove_function may have been called.
*
* @param connection the connection.
* @param add_function function to begin monitoring a new descriptor.
* @param remove_function function to stop monitoring a descriptor.
* @param data data to pass to add_function and remove_function.
* @param free_data_function function to be called to free the data.
* @returns #FALSE on failure (no memory)
*/
void
dbus_bool_t
dbus_connection_set_watch_functions (DBusConnection *connection,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
void *data,
DBusFreeFunction free_data_function)
{
dbus_bool_t retval;
dbus_mutex_lock (connection->mutex);
/* ref connection for slightly better reentrancy */
_dbus_connection_ref_unlocked (connection);
_dbus_watch_list_set_functions (connection->watches,
add_function, remove_function,
data, free_data_function);
retval = _dbus_watch_list_set_functions (connection->watches,
add_function, remove_function,
data, free_data_function);
dbus_mutex_unlock (connection->mutex);
/* drop our paranoid refcount */
dbus_connection_unref (connection);
return retval;
}
/**
@ -1855,25 +1868,30 @@ dbus_connection_set_watch_functions (DBusConnection *connection,
* @param remove_function function to remove a timeout.
* @param data data to pass to add_function and remove_function.
* @param free_data_function function to be called to free the data.
* @returns #FALSE on failure (no memory)
*/
void
dbus_bool_t
dbus_connection_set_timeout_functions (DBusConnection *connection,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_function,
void *data,
DBusFreeFunction free_data_function)
{
dbus_bool_t retval;
dbus_mutex_lock (connection->mutex);
/* ref connection for slightly better reentrancy */
_dbus_connection_ref_unlocked (connection);
_dbus_timeout_list_set_functions (connection->timeouts,
add_function, remove_function,
data, free_data_function);
retval = _dbus_timeout_list_set_functions (connection->timeouts,
add_function, remove_function,
data, free_data_function);
dbus_mutex_unlock (connection->mutex);
/* drop our paranoid refcount */
dbus_connection_unref (connection);
dbus_connection_unref (connection);
return retval;
}
/**

View file

@ -56,17 +56,15 @@ typedef enum
* can be present in current state). */
} DBusWatchFlags;
typedef void (* DBusAddWatchFunction) (DBusWatch *watch,
void *data);
typedef void (* DBusRemoveWatchFunction) (DBusWatch *watch,
void *data);
typedef void (* DBusWakeupMainFunction) (void *data);
typedef void (* DBusAddTimeoutFunction) (DBusTimeout *timeout,
void *data);
typedef void (* DBusRemoveTimeoutFunction) (DBusTimeout *timeout,
void *data);
typedef dbus_bool_t (* DBusAddWatchFunction) (DBusWatch *watch,
void *data);
typedef void (* DBusRemoveWatchFunction) (DBusWatch *watch,
void *data);
typedef void (* DBusWakeupMainFunction) (void *data);
typedef dbus_bool_t (* DBusAddTimeoutFunction) (DBusTimeout *timeout,
void *data);
typedef void (* DBusRemoveTimeoutFunction) (DBusTimeout *timeout,
void *data);
DBusConnection* dbus_connection_open (const char *address,
DBusResultCode *result);
@ -99,24 +97,24 @@ DBusMessage *dbus_connection_send_with_reply_and_block (DBusConnection *conn
DBusError *error);
dbus_bool_t dbus_connection_set_watch_functions (DBusConnection *connection,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
void *data,
DBusFreeFunction free_data_function);
dbus_bool_t dbus_connection_set_timeout_functions (DBusConnection *connection,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_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_handle_watch (DBusConnection *connection,
DBusWatch *watch,
unsigned int condition);
void dbus_connection_set_watch_functions (DBusConnection *connection,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
void *data,
DBusFreeFunction free_data_function);
void dbus_connection_set_timeout_functions (DBusConnection *connection,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_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_handle_watch (DBusConnection *connection,
DBusWatch *watch,
unsigned int condition);

View file

@ -392,19 +392,20 @@ dbus_server_set_new_connection_function (DBusServer *server,
* @param remove_function function to stop monitoring a descriptor.
* @param data data to pass to add_function and remove_function.
* @param free_data_function function to be called to free the data.
* @returns #FALSE on failure (no memory)
*/
void
dbus_bool_t
dbus_server_set_watch_functions (DBusServer *server,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
void *data,
DBusFreeFunction free_data_function)
{
_dbus_watch_list_set_functions (server->watches,
add_function,
remove_function,
data,
free_data_function);
return _dbus_watch_list_set_functions (server->watches,
add_function,
remove_function,
data,
free_data_function);
}
/**
@ -419,17 +420,18 @@ dbus_server_set_watch_functions (DBusServer *server,
* @param remove_function function to remove a timeout.
* @param data data to pass to add_function and remove_function.
* @param free_data_function function to be called to free the data.
* @returns #FALSE on failure (no memory)
*/
void
dbus_bool_t
dbus_server_set_timeout_functions (DBusServer *server,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_function,
void *data,
DBusFreeFunction free_data_function)
{
_dbus_timeout_list_set_functions (server->timeouts,
add_function, remove_function,
data, free_data_function);
return _dbus_timeout_list_set_functions (server->timeouts,
add_function, remove_function,
data, free_data_function);
}
/**

View file

@ -45,31 +45,28 @@ void dbus_server_ref (DBusServer *server);
void dbus_server_unref (DBusServer *server);
void dbus_server_disconnect (DBusServer *server);
dbus_bool_t dbus_server_get_is_connected (DBusServer *server);
void dbus_server_set_new_connection_function (DBusServer *server,
DBusNewConnectionFunction function,
void *data,
DBusFreeFunction free_data_function);
dbus_bool_t dbus_server_set_watch_functions (DBusServer *server,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
void *data,
DBusFreeFunction free_data_function);
dbus_bool_t dbus_server_set_timeout_functions (DBusServer *server,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_function,
void *data,
DBusFreeFunction free_data_function);
void dbus_server_handle_watch (DBusServer *server,
DBusWatch *watch,
unsigned int condition);
void dbus_server_set_max_connections (DBusServer *server,
int max_connections);
int dbus_server_get_max_connections (DBusServer *server);
int dbus_server_get_n_connections (DBusServer *server);
void dbus_server_set_new_connection_function (DBusServer *server,
DBusNewConnectionFunction function,
void *data,
DBusFreeFunction free_data_function);
void dbus_server_set_watch_functions (DBusServer *server,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
void *data,
DBusFreeFunction free_data_function);
void dbus_server_set_timeout_functions (DBusServer *server,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_function,
void *data,
DBusFreeFunction free_data_function);
void dbus_server_handle_watch (DBusServer *server,
DBusWatch *watch,
unsigned int condition);
void dbus_server_set_max_connections (DBusServer *server,
int max_connections);
int dbus_server_get_max_connections (DBusServer *server);
int dbus_server_get_n_connections (DBusServer *server);
int dbus_server_allocate_data_slot (void);
void dbus_server_free_data_slot (int slot);

View file

@ -181,15 +181,50 @@ _dbus_timeout_list_free (DBusTimeoutList *timeout_list)
* @param remove_function the remove timeout function.
* @param data the data for those functions.
* @param free_data_function the function to free the data.
* @returns #FALSE if no memory
*
*/
void
dbus_bool_t
_dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_function,
void *data,
DBusFreeFunction free_data_function)
{
/* Add timeouts with the new function, failing on OOM */
if (add_function != NULL)
{
DBusList *link;
link = _dbus_list_get_first_link (&timeout_list->timeouts);
while (link != NULL)
{
DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
link);
if (!(* add_function) (link->data, data))
{
/* remove it all again and return FALSE */
DBusList *link2;
link2 = _dbus_list_get_first_link (&timeout_list->timeouts);
while (link2 != link)
{
DBusList *next = _dbus_list_get_next_link (&timeout_list->timeouts,
link2);
(* remove_function) (link2->data, data);
link2 = next;
}
return FALSE;
}
link = next;
}
}
/* Remove all current timeouts from previous timeout handlers */
if (timeout_list->remove_timeout_function != NULL)
@ -207,13 +242,7 @@ _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list,
timeout_list->timeout_data = data;
timeout_list->timeout_free_data_function = free_data_function;
/* Re-add all pending timeouts */
if (timeout_list->add_timeout_function != NULL)
{
_dbus_list_foreach (&timeout_list->timeouts,
(DBusForeachFunction) timeout_list->add_timeout_function,
timeout_list->timeout_data);
}
return TRUE;
}
/**
@ -234,14 +263,21 @@ _dbus_timeout_list_add_timeout (DBusTimeoutList *timeout_list,
_dbus_timeout_ref (timeout);
if (timeout_list->add_timeout_function != NULL)
(* timeout_list->add_timeout_function) (timeout,
timeout_list->timeout_data);
{
if (!(* timeout_list->add_timeout_function) (timeout,
timeout_list->timeout_data))
{
_dbus_list_remove_last (&timeout_list->timeouts, timeout);
_dbus_timeout_unref (timeout);
return FALSE;
}
}
return TRUE;
}
/**
* Removes a timeout from the watch list, invoking the
* Removes a timeout from the timeout list, invoking the
* application's DBusRemoveTimeoutFunction if appropriate.
*
* @param timeout_list the timeout list.

View file

@ -44,7 +44,7 @@ void _dbus_timeout_unref (DBusTimeout *timeout);
DBusTimeoutList *_dbus_timeout_list_new (void);
void _dbus_timeout_list_free (DBusTimeoutList *timeout_list);
void _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list,
dbus_bool_t _dbus_timeout_list_set_functions (DBusTimeoutList *timeout_list,
DBusAddTimeoutFunction add_function,
DBusRemoveTimeoutFunction remove_function,
void *data,

View file

@ -159,7 +159,7 @@ struct DBusWatchList
DBusList *watches; /**< Watch objects. */
DBusAddWatchFunction add_watch_function; /**< Callback for adding a watch. */
DBusAddWatchFunction remove_watch_function; /**< Callback for removing a watch. */
DBusRemoveWatchFunction remove_watch_function; /**< Callback for removing a watch. */
void *watch_data; /**< Data for watch callbacks */
DBusFreeFunction watch_free_data_function; /**< Free function for watch callback data */
};
@ -212,15 +212,50 @@ _dbus_watch_list_free (DBusWatchList *watch_list)
* @param remove_function the remove watch function.
* @param data the data for those functions.
* @param free_data_function the function to free the data.
* @returns #FALSE if not enough memory
*
*/
void
dbus_bool_t
_dbus_watch_list_set_functions (DBusWatchList *watch_list,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
void *data,
DBusFreeFunction free_data_function)
{
/* Add watches with the new watch function, failing on OOM */
if (add_function != NULL)
{
DBusList *link;
link = _dbus_list_get_first_link (&watch_list->watches);
while (link != NULL)
{
DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
link);
if (!(* add_function) (link->data, data))
{
/* remove it all again and return FALSE */
DBusList *link2;
link2 = _dbus_list_get_first_link (&watch_list->watches);
while (link2 != link)
{
DBusList *next = _dbus_list_get_next_link (&watch_list->watches,
link2);
(* remove_function) (link2->data, data);
link2 = next;
}
return FALSE;
}
link = next;
}
}
/* Remove all current watches from previous watch handlers */
if (watch_list->remove_watch_function != NULL)
@ -238,13 +273,7 @@ _dbus_watch_list_set_functions (DBusWatchList *watch_list,
watch_list->watch_data = data;
watch_list->watch_free_data_function = free_data_function;
/* Re-add all pending watches */
if (watch_list->add_watch_function != NULL)
{
_dbus_list_foreach (&watch_list->watches,
(DBusForeachFunction) watch_list->add_watch_function,
watch_list->watch_data);
}
return TRUE;
}
/**
@ -265,8 +294,15 @@ _dbus_watch_list_add_watch (DBusWatchList *watch_list,
_dbus_watch_ref (watch);
if (watch_list->add_watch_function != NULL)
(* watch_list->add_watch_function) (watch,
watch_list->watch_data);
{
if (!(* watch_list->add_watch_function) (watch,
watch_list->watch_data))
{
_dbus_list_remove_last (&watch_list->watches, watch);
_dbus_watch_unref (watch);
return FALSE;
}
}
return TRUE;
}

View file

@ -43,7 +43,7 @@ void _dbus_watch_sanitize_condition (DBusWatch *watch,
DBusWatchList* _dbus_watch_list_new (void);
void _dbus_watch_list_free (DBusWatchList *watch_list);
void _dbus_watch_list_set_functions (DBusWatchList *watch_list,
dbus_bool_t _dbus_watch_list_set_functions (DBusWatchList *watch_list,
DBusAddWatchFunction add_function,
DBusRemoveWatchFunction remove_function,
void *data,

View file

@ -231,7 +231,7 @@ dbus_server_dispatch (GSource *source,
return TRUE;
}
static void
static dbus_bool_t
add_watch (DBusWatch *watch,
gpointer data)
{
@ -257,6 +257,8 @@ add_watch (DBusWatch *watch,
dbus_source->poll_fds = g_list_prepend (dbus_source->poll_fds, poll_fd);
g_hash_table_insert (dbus_source->watches, poll_fd, watch);
return TRUE;
}
static void
@ -285,7 +287,7 @@ timeout_handler (gpointer data)
return FALSE;
}
static void
static dbus_bool_t
add_timeout (DBusTimeout *timeout,
void *data)
{
@ -295,6 +297,8 @@ add_timeout (DBusTimeout *timeout,
timeout_handler, timeout);
dbus_timeout_set_data (timeout, GUINT_TO_POINTER (timeout_tag), NULL);
return TRUE;
}
static void
@ -356,16 +360,18 @@ dbus_connection_setup_with_g_main (DBusConnection *connection)
source = create_source (connection, &dbus_connection_funcs);
dbus_connection_set_watch_functions (connection,
add_watch,
remove_watch,
source, NULL);
if (!dbus_connection_set_watch_functions (connection,
add_watch,
remove_watch,
source, NULL))
goto nomem;
dbus_connection_set_timeout_functions (connection,
add_timeout,
remove_timeout,
NULL, NULL);
if (!dbus_connection_set_timeout_functions (connection,
add_timeout,
remove_timeout,
NULL, NULL))
goto nomem;
dbus_connection_set_wakeup_main_function (connection,
wakeup_main,
NULL, NULL);

View file

@ -45,19 +45,26 @@ free_watch_data (void *data)
dbus_free (wd);
}
static void
static dbus_bool_t
add_connection_watch (DBusWatch *watch,
DBusConnection *connection)
{
WatchData *wd;
if (!_dbus_list_append (&watches, watch))
return FALSE;
wd = dbus_new0 (WatchData, 1);
if (wd == NULL)
{
_dbus_list_remove_last (&watches, watch);
return FALSE;
}
wd->type = WATCH_CONNECTION;
wd->data = connection;
dbus_connection_ref (connection);
_dbus_list_append (&watches, watch);
dbus_connection_ref (connection);
dbus_watch_set_data (watch, wd, free_watch_data);
watch_list_serial += 1;
@ -67,6 +74,8 @@ add_connection_watch (DBusWatch *watch,
dbus_watch_get_flags (watch) & DBUS_WATCH_WRITABLE ? "write " : "",
dbus_watch_get_fd (watch));
#endif
return TRUE;
}
static void
@ -86,19 +95,26 @@ remove_connection_watch (DBusWatch *watch,
#endif
}
static void
static dbus_bool_t
add_server_watch (DBusWatch *watch,
DBusServer *server)
{
WatchData *wd;
if (!_dbus_list_append (&watches, watch))
return FALSE;
wd = dbus_new0 (WatchData, 1);
if (wd == NULL)
{
_dbus_list_remove_last (&watches, watch);
return FALSE;
}
wd->type = WATCH_SERVER;
wd->data = server;
dbus_server_ref (server);
_dbus_list_append (&watches, watch);
dbus_watch_set_data (watch, wd, free_watch_data);
@ -109,6 +125,8 @@ add_server_watch (DBusWatch *watch,
dbus_watch_get_flags (watch) & DBUS_WATCH_WRITABLE ? "write " : "",
dbus_watch_get_fd (watch));
#endif
return TRUE;
}
static void
@ -324,11 +342,12 @@ quit_mainloop (void)
void
setup_connection (DBusConnection *connection)
{
dbus_connection_set_watch_functions (connection,
(DBusAddWatchFunction) add_connection_watch,
(DBusRemoveWatchFunction) remove_connection_watch,
connection,
NULL);
if (!dbus_connection_set_watch_functions (connection,
(DBusAddWatchFunction) add_connection_watch,
(DBusRemoveWatchFunction) remove_connection_watch,
connection,
NULL))
_dbus_assert_not_reached ("not enough memory");
dbus_connection_ref (connection);
_dbus_list_append (&connections, connection);
@ -337,9 +356,10 @@ setup_connection (DBusConnection *connection)
void
setup_server (DBusServer *server)
{
dbus_server_set_watch_functions (server,
(DBusAddWatchFunction) add_server_watch,
(DBusRemoveWatchFunction) remove_server_watch,
server,
NULL);
if (!dbus_server_set_watch_functions (server,
(DBusAddWatchFunction) add_server_watch,
(DBusRemoveWatchFunction) remove_server_watch,
server,
NULL))
_dbus_assert_not_reached ("not enough memory");
}