PATCH: Implicit activation
Richard Hult
richard@imendio.com
Fri Mar 12 00:39:38 PST 2004
--=-roK24e5WA8RjmEsD2WNf
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
Hi!
This patch implements implicit activation as discussed here earlier. An
implicit activation is done by setting a flag on the message before it's
sent off.
The exact spots where to do the adding to/sending of pending messages
could be argued, so some refactoring might be needed. I also need to go
through the patch and make sure that we cover all the cases of error
conditions from the design. Here comes a first version.
/Richard
--
Richard Hult richard@imendio.com
Imendio http://www.imendio.com
--=-roK24e5WA8RjmEsD2WNf
Content-Disposition: attachment; filename=implact.diff
Content-Type: text/x-patch; name=implact.diff; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit
Index: bus/activation.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/activation.c,v
retrieving revision 1.31
diff -u -b -B -p -r1.31 activation.c
--- a/bus/activation.c 2 Dec 2003 10:44:21 -0000 1.31
+++ b/bus/activation.c 12 Mar 2004 00:10:28 -0000
@@ -63,6 +63,8 @@ struct BusPendingActivationEntry
{
DBusMessage *activation_message;
DBusConnection *connection;
+
+ dbus_bool_t implicit_activation;
};
typedef struct
@@ -603,6 +605,9 @@ bus_activation_service_created (BusActiv
if (dbus_connection_get_is_connected (entry->connection))
{
+ /* Only send activation replies to regular activation requests. */
+ if (!entry->implicit_activation)
+ {
message = dbus_message_new_method_return (entry->activation_message);
if (!message)
{
@@ -628,6 +633,63 @@ bus_activation_service_created (BusActiv
dbus_message_unref (message);
}
+ }
+
+ link = next;
+ }
+
+ return TRUE;
+
+ error:
+ return FALSE;
+}
+
+dbus_bool_t
+bus_activation_send_pending_implicit_activation_messages (BusActivation *activation,
+ BusService *service,
+ BusTransaction *transaction,
+ DBusError *error)
+{
+ BusPendingActivation *pending_activation;
+ DBusList *link;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ /* Check if it's a pending activation */
+ pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations,
+ bus_service_get_name (service));
+
+ if (!pending_activation)
+ return TRUE;
+
+ link = _dbus_list_get_first_link (&pending_activation->entries);
+ while (link != NULL)
+ {
+ BusPendingActivationEntry *entry = link->data;
+ DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link);
+
+ if (entry->implicit_activation && dbus_connection_get_is_connected (entry->connection))
+ {
+ DBusConnection *addressed_recipient;
+
+ addressed_recipient = bus_service_get_primary_owner (service);
+
+ /* Check the security policy, which has the side-effect of adding an
+ * expected pending reply.
+ */
+ if (!bus_context_check_security_policy (activation->context, transaction,
+ entry->connection,
+ addressed_recipient,
+ addressed_recipient,
+ entry->activation_message, error))
+ goto error;
+
+ if (!bus_transaction_send (transaction, addressed_recipient, entry->activation_message))
+ {
+ BUS_SET_OOM (error);
+ goto error;
+ }
+ }
link = next;
}
@@ -639,7 +701,7 @@ bus_activation_service_created (BusActiv
goto error;
}
- _dbus_hash_table_remove_string (activation->pending_activations, service_name);
+ _dbus_hash_table_remove_string (activation->pending_activations, bus_service_get_name (service));
return TRUE;
@@ -844,6 +906,7 @@ dbus_bool_t
bus_activation_activate_service (BusActivation *activation,
DBusConnection *connection,
BusTransaction *transaction,
+ dbus_bool_t implicit_activation,
DBusMessage *activation_message,
const char *service_name,
DBusError *error)
@@ -921,6 +984,8 @@ bus_activation_activate_service (BusActi
return FALSE;
}
+ pending_activation_entry->implicit_activation = implicit_activation;
+
pending_activation_entry->activation_message = activation_message;
dbus_message_ref (activation_message);
pending_activation_entry->connection = connection;
Index: bus/activation.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/activation.h,v
retrieving revision 1.11
diff -u -b -B -p -r1.11 activation.h
--- a/bus/activation.h 2 Dec 2003 10:44:21 -0000 1.11
+++ b/bus/activation.h 12 Mar 2004 00:10:28 -0000
@@ -37,6 +37,7 @@ void bus_activation_unref
dbus_bool_t bus_activation_activate_service (BusActivation *activation,
DBusConnection *connection,
BusTransaction *transaction,
+ dbus_bool_t implicit_activation,
DBusMessage *activation_message,
const char *service_name,
DBusError *error);
@@ -45,5 +46,11 @@ dbus_bool_t bus_activation_service_cr
BusTransaction *transaction,
DBusError *error);
+dbus_bool_t bus_activation_send_pending_implicit_activation_messages (BusActivation *activation,
+ BusService *service,
+ BusTransaction *transaction,
+ DBusError *error);
+
+
#endif /* BUS_ACTIVATION_H */
Index: bus/bus.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/bus.c,v
retrieving revision 1.48
diff -u -b -B -p -r1.48 bus.c
Index: bus/connection.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/connection.c,v
retrieving revision 1.53
diff -u -b -B -p -r1.53 connection.c
Index: bus/dispatch.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/dispatch.c,v
retrieving revision 1.56
diff -u -b -B -p -r1.56 dispatch.c
--- a/bus/dispatch.c 2 Dec 2003 10:44:21 -0000 1.56
+++ b/bus/dispatch.c 12 Mar 2004 00:10:29 -0000
@@ -26,6 +26,7 @@
#include "connection.h"
#include "driver.h"
#include "services.h"
+#include "activation.h"
#include "utils.h"
#include "bus.h"
#include "signals.h"
@@ -257,7 +258,27 @@ bus_dispatch (DBusConnection *connection
_dbus_string_init_const (&service_string, service_name);
service = bus_registry_lookup (registry, &service_string);
- if (service == NULL)
+ if (service == NULL && dbus_message_get_implicit_activation (message))
+ {
+ BusActivation *activation;
+
+ /* We can't do the security policy check here, since the addressed
+ * recipient service doesn't exist yet. We do it before sending the
+ * message after the service has been created.
+ */
+ activation = bus_connection_get_activation (connection);
+
+ if (!bus_activation_activate_service (activation, connection, transaction, TRUE,
+ message, service_name, &error))
+ {
+ _DBUS_ASSERT_ERROR_IS_SET (&error);
+ _dbus_verbose ("bus_activation_activate_service() failed\n");
+ goto out;
+ }
+
+ goto out;
+ }
+ else if (service == NULL)
{
dbus_set_error (&error,
DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
@@ -378,6 +399,8 @@ bus_dispatch_remove_connection (DBusConn
#ifdef DBUS_BUILD_TESTS
+#include <stdio.h>
+
typedef dbus_bool_t (* Check1Func) (BusContext *context);
typedef dbus_bool_t (* Check2Func) (BusContext *context,
DBusConnection *connection);
@@ -1170,6 +1193,104 @@ check_nonexistent_service_activation (Bu
return retval;
}
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_nonexistent_service_implicit_activation (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ DBusError error;
+
+ dbus_error_init (&error);
+
+ message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ dbus_message_set_implicit_activation (message, 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);
+ block_connection_until_message_from_bus (context, connection);
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (implicit activation)", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_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_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully activate %s\n",
+ NONEXISTENT_SERVICE_NAME);
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
static dbus_bool_t
check_base_service_activated (BusContext *context,
DBusConnection *connection,
@@ -1308,6 +1429,8 @@ check_service_activated (BusContext
}
}
+ printf ("*** Got service name (created): %s\n", service_name);
+
if (strcmp (service_name, activated_name) != 0)
{
_dbus_warn ("Expected to see service %s created, saw %s instead\n",
@@ -1398,6 +1522,94 @@ check_service_activated (BusContext
}
static dbus_bool_t
+check_service_implicitly_activated (BusContext *context,
+ DBusConnection *connection,
+ const char *activated_name,
+ const char *base_service_name,
+ DBusMessage *initial_message)
+{
+ DBusMessage *message;
+ dbus_bool_t retval;
+ DBusError error;
+
+ retval = FALSE;
+
+ dbus_error_init (&error);
+
+ message = initial_message;
+ dbus_message_ref (message);
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+ "ServiceCreated"))
+ {
+ char *service_name;
+ CheckServiceCreatedData scd;
+
+ reget_service_name_arg:
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &service_name,
+ DBUS_TYPE_INVALID))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ dbus_error_free (&error);
+ _dbus_wait_for_memory ();
+ goto reget_service_name_arg;
+ }
+ else
+ {
+ _dbus_warn ("Message %s doesn't have a service name: %s\n",
+ "ServiceCreated",
+ error.message);
+ dbus_error_free (&error);
+ goto out;
+ }
+ }
+
+ if (strcmp (service_name, activated_name) != 0)
+ {
+ _dbus_warn ("Expected to see service %s created, saw %s instead\n",
+ activated_name, service_name);
+ dbus_free (service_name);
+ goto out;
+ }
+
+ scd.skip_connection = connection;
+ scd.failed = FALSE;
+ scd.expected_service_name = service_name;
+ bus_test_clients_foreach (check_service_created_foreach,
+ &scd);
+
+ dbus_free (service_name);
+
+ if (scd.failed)
+ goto out;
+
+ /* Note that this differs from regular activation in that we don't get a
+ * reply to ActivateService here.
+ */
+
+ dbus_message_unref (message);
+ message = NULL;
+ }
+ else
+ {
+ warn_unexpected (connection, message, "ServiceCreated for the activated name");
+
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+static dbus_bool_t
check_service_deactivated (BusContext *context,
DBusConnection *connection,
const char *activated_name,
@@ -1974,63 +2186,490 @@ check_segfault_service_activation (BusCo
return retval;
}
-typedef struct
-{
- Check1Func func;
- BusContext *context;
-} Check1Data;
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
static dbus_bool_t
-check_oom_check1_func (void *data)
-{
- Check1Data *d = data;
-
- if (! (* d->func) (d->context))
- return FALSE;
-
- if (!check_no_leftovers (d->context))
- {
- _dbus_warn ("Messages were left over, should be covered by test suite\n");
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-check1_try_iterations (BusContext *context,
- const char *description,
- Check1Func func)
+check_segfault_service_implicit_activation (BusContext *context,
+ DBusConnection *connection)
{
- Check1Data d;
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ DBusError error;
- d.func = func;
- d.context = context;
+ dbus_error_init (&error);
- if (!_dbus_test_oom_handling (description, check_oom_check1_func,
- &d))
- _dbus_assert_not_reached ("test failed");
-}
+ dbus_error_init (&error);
-typedef struct
-{
- Check2Func func;
- BusContext *context;
- DBusConnection *connection;
-} Check2Data;
+ message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
-static dbus_bool_t
-check_oom_check2_func (void *data)
-{
- Check2Data *d = data;
+ if (message == NULL)
+ return TRUE;
- if (! (* d->func) (d->context, d->connection))
- return FALSE;
+ dbus_message_set_implicit_activation (message, TRUE);
- if (!check_no_leftovers (d->context))
+ if (!dbus_connection_send (connection, message, &serial))
{
- _dbus_warn ("Messages were left over, should be covered by test suite");
- return FALSE;
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ bus_test_run_everything (context);
+ block_connection_until_message_from_bus (context, connection);
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+ "Echo message (implicit activation)", serial, connection);
+ goto out;
+ }
+
+ verbose_message_received (connection, message);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_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_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_SIGNALED))
+ {
+ ; /* good, this is expected also */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else
+ {
+ _dbus_warn ("Did not expect to successfully activate segfault service\n");
+ goto out;
+ }
+
+ retval = TRUE;
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ return retval;
+}
+
+#define TEST_ECHO_MESSAGE "Test echo message"
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
+check_existent_service_implicit_activation (BusContext *context,
+ DBusConnection *connection)
+{
+ DBusMessage *message;
+ dbus_uint32_t serial;
+ dbus_bool_t retval;
+ DBusError error;
+ char *base_service;
+ static int i = 1;
+
+ base_service = NULL;
+
+ printf ("New run: %d\n\n", i++);
+
+ dbus_error_init (&error);
+
+ message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
+ "/org/freedesktop/TestSuite",
+ "org.freedesktop.TestSuite",
+ "Echo");
+
+ if (message == NULL)
+ return TRUE;
+
+ dbus_message_set_implicit_activation (message, TRUE);
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, TEST_ECHO_MESSAGE,
+ DBUS_TYPE_INVALID))
+ {
+ dbus_message_unref (message);
+ return TRUE;
+ }
+
+ printf ("Q: Send impl.act message, %p\n", message);
+
+ serial = 0;
+ if (!dbus_connection_send_with_reply (connection, message, NULL, 3000))//&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.
+ */
+
+ printf ("Q: block until message from bus (1)\n");
+ block_connection_until_message_from_bus (context, connection);
+
+ bus_test_run_everything (context);
+
+ if (!dbus_connection_get_is_connected (connection))
+ {
+ _dbus_verbose ("connection was disconnected\n");
+ return TRUE;
+ }
+
+ retval = FALSE;
+
+ /* Should get ServiceCreated for the base service, or an error, unless the
+ * service was already running, then we get the reply immediately.
+ */
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive any messages after implicit activation %d on %p\n",
+ serial, connection);
+ goto out;
+ }
+
+ printf ("Q: Checking for ServiceCreated or error\n");
+
+ verbose_message_received (connection, message);
+ _dbus_verbose (" (after sending %s)\n", "ActivateService");
+
+ printf ("Q: Noticing reply serial: %d, orig: %d (if same => already activated)\n",
+ dbus_message_get_reply_serial (message), serial);
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ printf ("Q: Got error\n");
+
+ if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
+ {
+ _dbus_warn ("Message has wrong sender %s\n",
+ dbus_message_get_sender (message) ?
+ dbus_message_get_sender (message) : "(none)");
+ printf ("Q: Error has wrong sender\n");
+ goto out;
+ }
+
+ if (dbus_message_is_error (message,
+ DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ printf ("Q: Got NO_MEMORY error\n");
+ }
+ else if (dbus_message_is_error (message,
+ DBUS_ERROR_SPAWN_CHILD_EXITED))
+ {
+ ; /* good, this is expected also */
+ printf ("Q: Got CHILD_EXITED error\n");
+ }
+ else
+ {
+ _dbus_warn ("Did not expect error %s\n",
+ dbus_message_get_error_name (message));
+ printf ("Q: Invalid error\n");
+ goto out;
+ }
+ }
+ else if (TRUE || dbus_message_get_reply_serial (message) != serial)
+ {
+ dbus_bool_t got_service_deleted;
+ dbus_bool_t got_error;
+
+ printf ("Q: Check for base service ServiceCreated\n");
+
+ /* Since this is not a reply to the sent message, it should be a
+ * ServiceCreated for the base service or an error.
+ */
+ if (!check_base_service_activated (context, connection,
+ message, &base_service))
+ goto out;
+
+ printf ("Q: Base service created OK\n");
+
+ dbus_message_unref (message);
+ message = NULL;
+
+ printf ("Q: block until message from bus (2)\n");
+
+ /* We may need to block here for the test service to exit or finish up */
+ block_connection_until_message_from_bus (context, connection);
+
+ /* Should get ServiceCreated for the activated service name,
+ * ServiceDeleted on the base service name, or an error.
+ */
+ message = dbus_connection_borrow_message (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Did not receive any messages after base service creation notification\n");
+ goto out;
+ }
+
+ got_service_deleted = dbus_message_is_signal (message,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+ "ServiceDeleted");
+ got_error = dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
+
+ printf ("Q: got_service_deleted: %d, got_error: %d\n", got_service_deleted, got_error);
+
+ dbus_connection_return_message (connection, message);
+ message = NULL;
+
+ if (got_error)
+ {
+ if (!check_got_error (context, connection,
+ DBUS_ERROR_SPAWN_CHILD_EXITED,
+ DBUS_ERROR_NO_MEMORY,
+ NULL))
+ goto out;
+
+ printf ("Q: Got correct error (no_memory)\n");
+
+ /* A service deleted should be coming along now after this error.
+ * We can also get the error *after* the service deleted.
+ */
+ got_service_deleted = TRUE;
+ }
+
+ if (got_service_deleted)
+ {
+ /* The service started up and got a base address, but then
+ * failed to register under EXISTENT_SERVICE_NAME
+ */
+ CheckServiceDeletedData csdd;
+
+ csdd.expected_service_name = base_service;
+ csdd.failed = FALSE;
+ bus_test_clients_foreach (check_service_deleted_foreach,
+ &csdd);
+
+ if (csdd.failed)
+ goto out;
+
+ /* Now we should get an error about the service exiting
+ * if we didn't get it before.
+ */
+ if (!got_error)
+ {
+ printf ("Q: Didn't get error yet, wait for it\n");
+
+ block_connection_until_message_from_bus (context, connection);
+
+ /* and process everything again */
+ bus_test_run_everything (context);
+
+ if (!check_got_error (context, connection,
+ DBUS_ERROR_SPAWN_CHILD_EXITED,
+ NULL))
+ goto out;
+ }
+ }
+ else
+ {
+ message = pop_message_waiting_for_memory (connection);
+ if (message == NULL)
+ {
+ _dbus_warn ("Failed to pop message we just put back! should have been a ServiceCreated\n");
+ goto out;
+ }
+
+ printf ("Q: Check for ServiceCreated for named service...\n");
+
+ /* Check that ServiceCreated was correctly received */
+ if (!check_service_implicitly_activated (context, connection, EXISTENT_SERVICE_NAME,
+ base_service, message))
+ goto out;
+
+ printf ("Q: ...check OK\n");
+
+ dbus_message_unref (message);
+ message = NULL;
+ }
+
+ printf ("Q: block until message from bus (3)\n");
+ block_connection_until_message_from_bus (context, connection);
+
+ message = pop_message_waiting_for_memory (connection);
+ }
+
+ /* If we got this far, we should receive a reply or an error from the echo
+ * service.
+ */
+
+ printf ("Q: Check reply or error from echo service\n");
+
+ if (message == NULL)
+ {
+ _dbus_warn ("Expected a reply to %s, got nothing\n",
+ "Echo (implicit activation)");
+ goto out;
+ }
+
+ if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
+ {
+ ; /* good, this is a valid response */
+ }
+ else
+ {
+ warn_unexpected (connection, message, "not this error");
+
+ goto out;
+ }
+ }
+ else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+ {
+ char *str = NULL;
+
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &str,
+ DBUS_TYPE_INVALID))
+ {
+ if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
+ {
+ _dbus_verbose ("no memory to get echoed string\n");
+ }
+ else
+ {
+ _dbus_assert (dbus_error_is_set (&error));
+ _dbus_warn ("Did not get the expected single string argument\n");
+ goto out;
+ }
+ }
+ else if (strcmp (str, TEST_ECHO_MESSAGE) != 0)
+ {
+ _dbus_warn ("Expected an echo reply argument of '%s', got '%s'\n",
+ TEST_ECHO_MESSAGE, str);
+ goto out;
+ }
+ else
+ {
+ printf ("Got echoed message: '%s'\n", str);
+ }
+
+ dbus_free (str);
+ }
+
+ if (!check_no_leftovers (context))
+ {
+ _dbus_warn ("Messages were left over after successful activation\n");
+ goto out;
+ }
+
+ if (!check_send_exit_to_service (context, connection,
+ EXISTENT_SERVICE_NAME, base_service))
+ goto out;
+
+ retval = TRUE;
+
+ printf ("----\n");
+
+ out:
+ if (message)
+ dbus_message_unref (message);
+
+ if (base_service)
+ dbus_free (base_service);
+
+ return retval;
+}
+
+typedef struct
+{
+ Check1Func func;
+ BusContext *context;
+} Check1Data;
+
+static dbus_bool_t
+check_oom_check1_func (void *data)
+{
+ Check1Data *d = data;
+
+ if (! (* d->func) (d->context))
+ return FALSE;
+
+ if (!check_no_leftovers (d->context))
+ {
+ _dbus_warn ("Messages were left over, should be covered by test suite\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+check1_try_iterations (BusContext *context,
+ const char *description,
+ Check1Func func)
+{
+ Check1Data d;
+
+ d.func = func;
+ d.context = context;
+
+ if (!_dbus_test_oom_handling (description, check_oom_check1_func,
+ &d))
+ _dbus_assert_not_reached ("test failed");
+}
+
+typedef struct
+{
+ Check2Func func;
+ BusContext *context;
+ DBusConnection *connection;
+} Check2Data;
+
+static dbus_bool_t
+check_oom_check2_func (void *data)
+{
+ Check2Data *d = data;
+
+ if (! (* d->func) (d->context, d->connection))
+ return FALSE;
+
+ if (!check_no_leftovers (d->context))
+ {
+ _dbus_warn ("Messages were left over, should be covered by test suite");
+ return FALSE;
}
return TRUE;
@@ -2058,8 +2697,9 @@ bus_dispatch_test (const DBusString *tes
{
BusContext *context;
DBusConnection *foo;
- DBusConnection *bar;
+ /* DBusConnection *bar;
DBusConnection *baz;
+ */
DBusError error;
dbus_error_init (&error);
@@ -2068,7 +2708,7 @@ bus_dispatch_test (const DBusString *tes
"valid-config-files/debug-allow-all.conf");
if (context == NULL)
return FALSE;
-
+ /*
foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
if (foo == NULL)
_dbus_assert_not_reached ("could not alloc connection");
@@ -2131,6 +2771,46 @@ bus_dispatch_test (const DBusString *tes
kill_client_connection_unchecked (foo);
kill_client_connection_unchecked (bar);
kill_client_connection_unchecked (baz);
+ */
+
+ foo = dbus_connection_open ("debug-pipe:name=test-server", &error);
+ if (foo == NULL)
+ _dbus_assert_not_reached ("could not alloc connection");
+
+ if (!bus_setup_debug_client (foo))
+ _dbus_assert_not_reached ("could not set up connection");
+
+ if (!check_hello_message (context, foo))
+ _dbus_assert_not_reached ("hello message failed");
+
+ if (!check_add_match_all (context, foo))
+ _dbus_assert_not_reached ("AddMatch message failed");
+
+ if (!check_no_leftovers (context))
+ {
+ _dbus_warn ("Messages were left over after setting up initial connections");
+ _dbus_assert_not_reached ("initial connection setup failed");
+ }
+
+ if (0)
+ {
+ check2_try_iterations (context, foo, "nonexistent_implicit_service_activation",
+ check_nonexistent_service_implicit_activation);
+ }
+
+ if (0)
+ {
+ check2_try_iterations (context, foo, "segfault_implicit_service_activation",
+ check_segfault_service_implicit_activation);
+ }
+
+ if (1)
+ {
+ check2_try_iterations (context, foo, "existent_implicit_service_activation",
+ check_existent_service_implicit_activation);
+ }
+
+ kill_client_connection_unchecked (foo);
bus_context_unref (context);
Index: bus/driver.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/driver.c,v
retrieving revision 1.45
diff -u -b -B -p -r1.45 driver.c
--- a/bus/driver.c 2 Dec 2003 10:44:21 -0000 1.45
+++ b/bus/driver.c 12 Mar 2004 00:10:29 -0000
@@ -587,7 +587,7 @@ bus_driver_handle_activate_service (DBus
retval = FALSE;
- if (!bus_activation_activate_service (activation, connection, transaction,
+ if (!bus_activation_activate_service (activation, connection, transaction, FALSE,
message, name, error))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
Index: bus/services.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/services.c,v
retrieving revision 1.19
diff -u -b -B -p -r1.19 services.c
--- a/bus/services.c 24 Feb 2004 19:50:25 -0000 1.19
+++ b/bus/services.c 12 Mar 2004 00:10:29 -0000
@@ -262,6 +262,7 @@ bus_registry_acquire_service (BusRegistr
DBusConnection *current_owner;
BusClientPolicy *policy;
BusService *service;
+ BusActivation *activation;
retval = FALSE;
@@ -376,7 +377,11 @@ bus_registry_acquire_service (BusRegistr
*result = DBUS_SERVICE_REPLY_PRIMARY_OWNER;
}
- retval = TRUE;
+ activation = bus_context_get_activation (registry->context);
+ retval = bus_activation_send_pending_implicit_activation_messages (activation,
+ service,
+ transaction,
+ error);
out:
return retval;
Index: bus/signals.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/signals.c,v
retrieving revision 1.7
diff -u -b -B -p -r1.7 signals.c
Index: bus/test-main.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/test-main.c,v
retrieving revision 1.15
diff -u -b -B -p -r1.15 test-main.c
--- a/bus/test-main.c 2 Dec 2003 10:44:21 -0000 1.15
+++ b/bus/test-main.c 12 Mar 2004 00:10:29 -0000
@@ -77,7 +77,7 @@ main (int argc, char **argv)
die ("initializing debug threads");
#endif
- printf ("%s: Running expire list test\n", argv[0]);
+ /* printf ("%s: Running expire list test\n", argv[0]);
if (!bus_expire_list_test (&test_data_dir))
die ("expire list");
@@ -106,7 +106,7 @@ main (int argc, char **argv)
die ("sha1");
check_memleaks (argv[0]);
-
+ */
printf ("%s: Running message dispatch test\n", argv[0]);
if (!bus_dispatch_test (&test_data_dir))
die ("dispatch");
Index: bus/test.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/test.c,v
retrieving revision 1.23
diff -u -b -B -p -r1.23 test.c
Index: dbus/dbus-message.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message.c,v
retrieving revision 1.119
diff -u -b -B -p -r1.119 dbus-message.c
--- a/dbus/dbus-message.c 8 Mar 2004 10:29:16 -0000 1.119
+++ b/dbus/dbus-message.c 12 Mar 2004 00:10:30 -0000
@@ -4387,6 +4387,35 @@ dbus_message_get_no_reply (DBusMessage *
return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
}
+void
+dbus_message_set_implicit_activation (DBusMessage *message,
+ dbus_bool_t implicit_activation)
+{
+ char *header;
+
+ _dbus_return_if_fail (message != NULL);
+ _dbus_return_if_fail (!message->locked);
+
+ header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
+
+ if (implicit_activation)
+ *header |= DBUS_HEADER_FLAG_IMPLICIT_ACTIVATION;
+ else
+ *header &= ~DBUS_HEADER_FLAG_IMPLICIT_ACTIVATION;
+}
+
+dbus_bool_t
+dbus_message_get_implicit_activation (DBusMessage *message)
+{
+ const char *header;
+
+ _dbus_return_val_if_fail (message != NULL, FALSE);
+
+ header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
+
+ return (*header & DBUS_HEADER_FLAG_IMPLICIT_ACTIVATION) != 0;
+}
+
/**
* Gets the service which originated this message,
* or #NULL if unknown or inapplicable.
Index: dbus/dbus-message.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-message.h,v
retrieving revision 1.49
diff -u -b -B -p -r1.49 dbus-message.h
--- a/dbus/dbus-message.h 2 Dec 2003 10:44:21 -0000 1.49
+++ b/dbus/dbus-message.h 12 Mar 2004 00:10:30 -0000
@@ -119,6 +119,10 @@ dbus_bool_t dbus_message_set_reply_ser
dbus_uint32_t reply_serial);
dbus_uint32_t dbus_message_get_reply_serial (DBusMessage *message);
+void dbus_message_set_implicit_activation (DBusMessage *message,
+ dbus_bool_t implicit_activation);
+dbus_bool_t dbus_message_get_implicit_activation (DBusMessage *message);
+
dbus_bool_t dbus_message_get_path_decomposed (DBusMessage *message,
char ***path);
Index: dbus/dbus-protocol.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-protocol.h,v
retrieving revision 1.25
diff -u -b -B -p -r1.25 dbus-protocol.h
--- a/dbus/dbus-protocol.h 2 Dec 2003 10:44:21 -0000 1.25
+++ b/dbus/dbus-protocol.h 12 Mar 2004 00:10:30 -0000
@@ -72,6 +72,7 @@ extern "C" {
/* Header flags */
#define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED 0x1
+#define DBUS_HEADER_FLAG_IMPLICIT_ACTIVATION 0x2
/* Header fields */
#define DBUS_HEADER_FIELD_INVALID 0
Index: test/test-service.c
===================================================================
RCS file: /cvs/dbus/dbus/test/test-service.c,v
retrieving revision 1.14
diff -u -b -B -p -r1.14 test-service.c
--- a/test/test-service.c 21 Oct 2003 05:46:52 -0000 1.14
+++ b/test/test-service.c 12 Mar 2004 00:10:30 -0000
@@ -152,6 +152,13 @@ filter_func (DBusConnection *connect
}
else
{
+ if (dbus_message_get_type (message) == 3)
+ {
+ fprintf (stderr, "test-service got error from %s (%s)\n",
+ dbus_message_get_sender (message),
+ dbus_message_get_error_name (message));
+ }
+
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
}
--=-roK24e5WA8RjmEsD2WNf--
More information about the dbus
mailing list