From 0d18d39e983fd6b7ad0535d1622cec608b4622e3 Mon Sep 17 00:00:00 2001 From: Oliver Charles Date: Sun, 2 Feb 2014 10:24:49 +0000 Subject: [PATCH] switch-to-configuration.pl: Handle successful auto-restarts switch-to-configuration.pl is currently hard-coded to assume that if a unit is in the "auto-restart" state that something has gone wrong, but this is not strictly true. For example, I run offlineimap as a oneshot service restarting itself every minute (on success). NixOS currently thinks that offlineimap has failed to start as it enters the auto-restart state, because it doesn't consider why the unit failed. This commit changes switch-to-configuration.pl to inspect the full status of a unit in auto-restart state, and now only considers it failed if the ExecMainStatus is non-zero. --- .../activation/switch-to-configuration.pl | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/nixos/modules/system/activation/switch-to-configuration.pl b/nixos/modules/system/activation/switch-to-configuration.pl index 33ae3aef9fc..cb5b49692fe 100644 --- a/nixos/modules/system/activation/switch-to-configuration.pl +++ b/nixos/modules/system/activation/switch-to-configuration.pl @@ -93,8 +93,13 @@ sub parseFstab { sub parseUnit { my ($filename) = @_; + parseKeyValues(read_file($filename)); +} + +sub parseKeyValues { + my @lines = @_; my $info = {}; - foreach my $line (read_file($filename)) { + foreach my $line (@_) { # FIXME: not quite correct. $line =~ /^([^=]+)=(.*)$/ or next; $info->{$1} = $2; @@ -337,8 +342,21 @@ system("@systemd@/bin/systemctl", "reload", "dbus.service"); my (@failed, @new, @restarting); my $activeNew = getActiveUnits; while (my ($unit, $state) = each %{$activeNew}) { - push @failed, $unit if $state->{state} eq "failed" || $state->{substate} eq "auto-restart"; - push @new, $unit if $state->{state} ne "failed" && !defined $activePrev->{$unit}; + if ($state->{state} eq "failed") { + push @failed, $unit; + } + elsif ($state->{state} eq "auto-restart") { + # A unit in auto-restart state is a failure *if* it previously failed to start + my $lines = `@systemd@/bin/systemctl show '$unit'`; + my $info = parseKeyValues(split "\n", $lines); + + if ($info->{ExecMainStatus} ne '0') { + push @failed, $unit; + } + } + elsif ($state->{state} ne "failed" && !defined $activePrev->{$unit}) { + push @new, $unit; + } } print STDERR "the following new units were started: ", join(", ", sort(@new)), "\n"