Do not require systemd to have a service file if using it for activation
authorSimon McVittie <smcv@debian.org>
Fri, 27 Nov 2015 11:31:03 +0000 (11:31 +0000)
committerSimon McVittie <smcv@debian.org>
Wed, 2 Dec 2015 18:51:08 +0000 (18:51 +0000)
With --systemd-activation we special-case the name
org.freedesktop.systemd1 by assuming that it will eventually connect
to the bus. With that in mind, we can ignore whether it has a
.service file, and let it be "activated" regardless.

This fixes a regression test failure on non-systemd systems such
as the Ubuntu 14.04 OS on travis-ci.org: UpdateActivationEnvironment
failed, because it tried to update the (fake) systemd environment,
but because systemd was not actually installed, there was no
service file for it in the system's search paths. We could address this
by placing a dummy service file with Exec=/bin/false in our search path
like the real systemd does, but it seems cleaner to not require this;
this would eventually enable the real systemd to stop installing
that dummy service file.

This would not happen outside the regression tests, because there is
no sense in using --systemd-activation without systemd installed.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=93194
Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
bus/activation.c

index 7b1ab06..d1169e6 100644 (file)
@@ -1418,7 +1418,8 @@ pending_activation_finished_cb (DBusBabysitter *babysitter,
             {
               BusPendingActivation *p = _dbus_hash_iter_get_value (&iter);
 
-              if (p != pending_activation && strcmp (p->exec, pending_activation->exec) == 0)
+              if (p != pending_activation && p->exec != NULL &&
+                  strcmp (p->exec, pending_activation->exec) == 0)
                 pending_activation_failed (p, &error);
             }
 
@@ -1744,9 +1745,19 @@ bus_activation_activate_service (BusActivation  *activation,
       return FALSE;
     }
 
-  entry = activation_find_entry (activation, service_name, error);
-  if (!entry)
-    return FALSE;
+  if (bus_context_get_systemd_activation (activation->context) &&
+      strcmp (service_name, "org.freedesktop.systemd1") == 0)
+    {
+      /* if we're doing systemd activation, we assume systemd will connect
+       * eventually, and it does not need a .service file */
+      entry = NULL;
+    }
+  else
+    {
+      entry = activation_find_entry (activation, service_name, error);
+      if (!entry)
+        return FALSE;
+    }
 
   /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not
    * call us if the service is already active.
@@ -1853,17 +1864,20 @@ bus_activation_activate_service (BusActivation  *activation,
           return FALSE;
         }
 
-      pending_activation->exec = _dbus_strdup (entry->exec);
-      if (!pending_activation->exec)
+      if (entry != NULL)
         {
-          _dbus_verbose ("Failed to copy service exec for pending activation\n");
-          BUS_SET_OOM (error);
-          bus_pending_activation_unref (pending_activation);
-          bus_pending_activation_entry_free (pending_activation_entry);
-          return FALSE;
+          pending_activation->exec = _dbus_strdup (entry->exec);
+          if (!pending_activation->exec)
+            {
+              _dbus_verbose ("Failed to copy service exec for pending activation\n");
+              BUS_SET_OOM (error);
+              bus_pending_activation_unref (pending_activation);
+              bus_pending_activation_entry_free (pending_activation_entry);
+              return FALSE;
+            }
         }
 
-      if (entry->systemd_service)
+      if (entry != NULL && entry->systemd_service != NULL)
         {
           pending_activation->systemd_service = _dbus_strdup (entry->systemd_service);
           if (!pending_activation->systemd_service)
@@ -2055,6 +2069,11 @@ bus_activation_activate_service (BusActivation  *activation,
          proceed with traditional activation. */
     }
 
+  /* If entry was NULL, it would be because we were doing systemd activation
+   * and activating systemd itself; but we already handled that case with
+   * an early-return */
+  _dbus_assert (entry != NULL);
+
   /* use command as system and session different */
   if (!_dbus_string_init (&command))
     {