[PATCH 5/5] activation: implement upstart activation

Scott James Remnant scott at netsplit.com
Wed Dec 22 07:27:07 PST 2010


Upstart activation is performed by emitting a dbus-activation event
within Upstart, and then simply expecting the appropriate bus name
to appear.  e.g.

	start on dbus-activation org.freedesktop.UDisks
	exec /usr/lib/udisks/udsks-daemon
---
 bus/activation.c |  170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 170 insertions(+), 0 deletions(-)

diff --git a/bus/activation.c b/bus/activation.c
index 978fa00..198d6bf 100644
--- a/bus/activation.c
+++ b/bus/activation.c
@@ -1918,6 +1918,176 @@ bus_activation_activate_service (BusActivation  *activation,
   if (activated)
     return TRUE;
 
+  if (bus_context_get_activation_type (activation->context) == ACTIVATION_UPSTART)
+    {
+      BusRegistry *registry;
+      DBusString service_string;
+      BusService *service;
+
+      /* Check whether Upstart is connected */
+      registry = bus_connection_get_registry (connection);
+      _dbus_string_init_const (&service_string, "com.ubuntu.Upstart");
+      service = bus_registry_lookup (registry, &service_string);
+
+      if (entry->upstart_job
+          && (service != NULL))
+        {
+          BusTransaction *activation_transaction;
+          DBusMessageIter iter;
+          const char *event_name;
+          int wait_for_event;
+          DBusMessageIter array_iter;
+          DBusString entry;
+          const char *entry_str;
+          char **e;
+
+          /* Upstart activation is done by event; rather than naming a
+             job, we name the bus name to be activated; this is included
+             in the event environment along with the activation environment
+             so that gets passed correctly to jobs. */
+
+          /* Create the message */
+          message = dbus_message_new_method_call ("com.ubuntu.Upstart",
+                                                  "/com/ubuntu/Upstart",
+                                                  "com.ubuntu.Upstart0_6",
+                                                  "EmitEvent");
+          if (!message)
+            {
+              _dbus_verbose ("No memory to create activation message\n");
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+            {
+              _dbus_verbose ("No memory to set sender of activation message\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          dbus_message_iter_init_append (message, &iter);
+
+          event_name = "dbus-activation";
+          if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &event_name))
+            {
+              _dbus_verbose ("No memory to set args of activation message\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING,
+                                                 &array_iter))
+            {
+              _dbus_verbose ("No memory to set args of activation message\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          if (!_dbus_string_init (&entry))
+            {
+              _dbus_verbose ("No memory to create activation message environment\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          if (!_dbus_string_append_printf (&entry, "SERVICE=%s", service_name))
+            {
+              _dbus_verbose ("No memory to create activation message environment\n");
+              _dbus_string_free (&entry);
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          entry_str = _dbus_string_get_data (&entry);
+
+          if (!dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, &entry_str))
+            {
+              _dbus_verbose ("No memory to set args of activation message\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          _dbus_string_free (&entry);
+
+
+          envp = bus_activation_get_environment (activation);
+
+          if (envp == NULL)
+            {
+              _dbus_verbose ("No memory to get environment for activation message\n");
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          for (e = envp; *e; e++)
+            {
+              if (!dbus_message_iter_append_basic (&array_iter, DBUS_TYPE_STRING, e))
+                {
+                  _dbus_verbose ("No memory to set args of activation message\n");
+                  dbus_message_unref (message);
+                  dbus_free_string_array (envp);
+                  BUS_SET_OOM (error);
+                  return FALSE;
+                }
+            }
+
+          dbus_free_string_array (envp);
+
+          if (!dbus_message_iter_close_container (&iter, &array_iter))
+            {
+              _dbus_verbose ("No memory to set args of activation message\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+             }
+
+          wait_for_event = FALSE;
+          if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &wait_for_event))
+            {
+              _dbus_verbose ("No memory to set args of activation message\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          /* Create the transaction */
+          activation_transaction = bus_transaction_new (activation->context);
+          if (activation_transaction == NULL)
+            {
+              _dbus_verbose ("No memory to create activation transaction\n");
+              dbus_message_unref (message);
+              BUS_SET_OOM (error);
+              return FALSE;
+            }
+
+          retval = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service),
+                                           message, error);
+          dbus_message_unref (message);
+
+          if (!retval)
+            {
+              _DBUS_ASSERT_ERROR_IS_SET (error);
+              _dbus_verbose ("failed to send activation message: %s\n", error->name);
+              bus_transaction_cancel_and_free (activation_transaction);
+              return FALSE;
+            }
+
+          bus_transaction_execute_and_free (activation_transaction);
+
+          /* Now we just wait for the bus name to appear */
+          return TRUE;
+         }
+
+      /* Configured service without UpstartJob=, fallback to traditional
+         activation. */
+    }
+
   if (bus_context_get_activation_type (activation->context) == ACTIVATION_SYSTEMD)
     {
       if (strcmp (service_name, "org.freedesktop.systemd1") == 0)
-- 
1.7.1



More information about the dbus mailing list