Fix broken systemd shutdown services

The services systemd-random-seed-save.service and
systemd-update-utmp-shutdown.service from systemd 203 don't work,
because they have a RequiresMountFor dependency on /var/lib and
/var/log.  Such a dependency produces a cycle, causing systemd to drop
those services:

  Fixing conflicting jobs by deleting job poweroff.target/stop
  Deleting job systemd-poweroff.service/stop as dependency of job poweroff.target/stop
  Deleting job umount.target/stop as dependency of job systemd-poweroff.service/stop
  Deleting job -.mount/start as dependency of job umount.target/stop
  Deleting job systemd-random-seed-save.service/start as dependency of job -.mount/start
  Deleting job systemd-update-utmp-shutdown.service/start as dependency of job -.mount/start

Dropping the RequiresMountFor doesn't work either, because then
/var/... may have meen unmounted or remounted read-only.

Upstream systemd fixes this by doing the actual work from an ExecStop
action in an already-running service than conflicts with
shutdown.target.  So I backported that here.  The main consequence is
that wtmp shutdown records now get written properly.

The main lesson: shutdown.target is useless for pulling in services
during shutdown if they need to write anywhere.
This commit is contained in:
Eelco Dolstra 2013-09-22 21:04:54 +02:00
parent f5c4874b05
commit f19065c283
2 changed files with 45 additions and 13 deletions

View File

@ -76,6 +76,15 @@ rec {
'';
};
conflicts = mkOption {
default = [];
types = types.listOf types.string;
description = ''
If the specified units are started, then this unit is stopped
and vice versa.
'';
};
requiredBy = mkOption {
default = [];
types = types.listOf types.string;

View File

@ -73,13 +73,6 @@ let
"systemd-initctl.socket"
"systemd-initctl.service"
# Random seed.
"systemd-random-seed-load.service"
"systemd-random-seed-save.service"
# Utmp maintenance.
"systemd-update-utmp-shutdown.service"
# Kernel module loading.
#"systemd-modules-load.service"
@ -158,6 +151,7 @@ let
Before = concatStringsSep " " config.before;
BindsTo = concatStringsSep " " config.bindsTo;
PartOf = concatStringsSep " " config.partOf;
Conflicts = concatStringsSep " " config.conflicts;
"X-Restart-Triggers" = toString config.restartTriggers;
} // optionalAttrs (config.description != "") {
Description = config.description;
@ -600,13 +594,42 @@ in
users.extraGroups.systemd-journal.gid = config.ids.gids.systemd-journal;
# FIXME: This should no longer be needed with systemd >= 204.
systemd.services."systemd-update-utmp-reboot.service" =
{ description = "Update UTMP about System Reboot";
# FIXME: These are borrowed from upstream systemd.
systemd.services."systemd-update-utmp" =
{ description = "Update UTMP about System Reboot/Shutdown";
wantedBy = [ "sysinit.target" ];
unitConfig.DefaultDependencies = false;
serviceConfig.Type = "oneshot";
serviceConfig.ExecStart = "${systemd}/lib/systemd/systemd-update-utmp reboot";
after = [ "systemd-remount-fs.service" ];
before = [ "sysinit.target" "shutdown.target" ];
conflicts = [ "shutdown.target" ];
unitConfig = {
DefaultDependencies = false;
RequiresMountsFor = "/var/log";
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${systemd}/lib/systemd/systemd-update-utmp reboot";
ExecStop = "${systemd}/lib/systemd/systemd-update-utmp shutdown";
};
restartIfChanged = false;
};
systemd.services."systemd-random-seed" =
{ description = "Load/Save Random Seed";
wantedBy = [ "sysinit.target" "multi-user.target" ];
after = [ "systemd-remount-fs.service" ];
before = [ "sysinit.target" "shutdown.target" ];
conflicts = [ "shutdown.target" ];
unitConfig = {
DefaultDependencies = false;
RequiresMountsFor = "/var/lib";
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${systemd}/lib/systemd/systemd-random-seed load";
ExecStop = "${systemd}/lib/systemd/systemd-random-seed save";
};
};
};