···390 include serif fonts.
391 </para>
392 </listitem>
393+ <listitem>
394+ <para>
395+ The interface that allows activation scripts to restart units
396+ has been reworked. Restarting and reloading is now done by a
397+ single file
398+ <literal>/run/nixos/activation-restart-list</literal> that
399+ honors <literal>restartIfChanged</literal> and
400+ <literal>reloadIfChanged</literal> of the units.
401+ </para>
402+ </listitem>
403 </itemizedlist>
404 </section>
405 <section xml:id="sec-release-22.05-notable-changes">
+2
nixos/doc/manual/release-notes/rl-2205.section.md
···125 `pkgs.noto-fonts-cjk` is currently an alias of `pkgs.noto-fonts-cjk-sans` and
126 doesn't include serif fonts.
12700128## Other Notable Changes {#sec-release-22.05-notable-changes}
129130- The option [services.redis.servers](#opt-services.redis.servers) was added
···125 `pkgs.noto-fonts-cjk` is currently an alias of `pkgs.noto-fonts-cjk-sans` and
126 doesn't include serif fonts.
127128+- The interface that allows activation scripts to restart units has been reworked. Restarting and reloading is now done by a single file `/run/nixos/activation-restart-list` that honors `restartIfChanged` and `reloadIfChanged` of the units.
129+130## Other Notable Changes {#sec-release-22.05-notable-changes}
131132- The option [services.redis.servers](#opt-services.redis.servers) was added
···18my $restartListFile = "/run/nixos/restart-list";
19my $reloadListFile = "/run/nixos/reload-list";
2021-# Parse restart/reload requests by the activation script
000022my $restartByActivationFile = "/run/nixos/activation-restart-list";
23-my $reloadByActivationFile = "/run/nixos/activation-reload-list";
24my $dryRestartByActivationFile = "/run/nixos/dry-activation-restart-list";
25-my $dryReloadByActivationFile = "/run/nixos/dry-activation-reload-list";
2627make_path("/run/nixos", { mode => oct(755) });
28···382}
383384my @unitsToStopFiltered = filterUnits(\%unitsToStop);
385-my @unitsToStartFiltered = filterUnits(\%unitsToStart);
386387388# Show dry-run actions.
···395 print STDERR "would activate the configuration...\n";
396 system("$out/dry-activate", "$out");
397398- $unitsToRestart{$_} = 1 foreach
399- split('\n', read_file($dryRestartByActivationFile, err_mode => 'quiet') // "");
000400401- $unitsToReload{$_} = 1 foreach
402- split('\n', read_file($dryReloadByActivationFile, err_mode => 'quiet') // "");
0000000000000000403404 print STDERR "would restart systemd\n" if $restartSystemd;
405 print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n"
406 if scalar(keys %unitsToReload) > 0;
407 print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n"
408 if scalar(keys %unitsToRestart) > 0;
0409 print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n"
410 if scalar @unitsToStartFiltered;
411- unlink($dryRestartByActivationFile);
412- unlink($dryReloadByActivationFile);
413 exit 0;
414}
415···433system("$out/activate", "$out") == 0 or $res = 2;
434435# Handle the activation script requesting the restart or reload of a unit.
436-# We can only restart and reload (not stop/start) because the units to be
437-# stopped are already stopped before the activation script is run.
438-$unitsToRestart{$_} = 1 foreach
439- split('\n', read_file($restartByActivationFile, err_mode => 'quiet') // "");
440441-$unitsToReload{$_} = 1 foreach
442- split('\n', read_file($reloadByActivationFile, err_mode => 'quiet') // "");
000000000000000000443444# Restart systemd if necessary. Note that this is done using the
445# current version of systemd, just in case the new one has trouble
···480 print STDERR "reloading the following units: ", join(", ", sort(keys %unitsToReload)), "\n";
481 system("@systemd@/bin/systemctl", "reload", "--", sort(keys %unitsToReload)) == 0 or $res = 4;
482 unlink($reloadListFile);
483- unlink($reloadByActivationFile);
484}
485486# Restart changed services (those that have to be restarted rather
···489 print STDERR "restarting the following units: ", join(", ", sort(keys %unitsToRestart)), "\n";
490 system("@systemd@/bin/systemctl", "restart", "--", sort(keys %unitsToRestart)) == 0 or $res = 4;
491 unlink($restartListFile);
492- unlink($restartByActivationFile);
493}
494495# Start all active targets, as well as changed units we stopped above.
···498# that are symlinks to other units. We shouldn't start both at the
499# same time because we'll get a "Failed to add path to set" error from
500# systemd.
0501print STDERR "starting the following units: ", join(", ", @unitsToStartFiltered), "\n"
502 if scalar @unitsToStartFiltered;
503system("@systemd@/bin/systemctl", "start", "--", sort(keys %unitsToStart)) == 0 or $res = 4;
···18my $restartListFile = "/run/nixos/restart-list";
19my $reloadListFile = "/run/nixos/reload-list";
2021+# Parse restart/reload requests by the activation script.
22+# Activation scripts may write newline-separated units to this
23+# file and switch-to-configuration will handle them. While
24+# `stopIfChanged = true` is ignored, switch-to-configuration will
25+# handle `restartIfChanged = false` and `reloadIfChanged = true`.
26my $restartByActivationFile = "/run/nixos/activation-restart-list";
027my $dryRestartByActivationFile = "/run/nixos/dry-activation-restart-list";
02829make_path("/run/nixos", { mode => oct(755) });
30···384}
385386my @unitsToStopFiltered = filterUnits(\%unitsToStop);
0387388389# Show dry-run actions.
···396 print STDERR "would activate the configuration...\n";
397 system("$out/dry-activate", "$out");
398399+ # Handle the activation script requesting the restart or reload of a unit.
400+ foreach (split('\n', read_file($dryRestartByActivationFile, err_mode => 'quiet') // "")) {
401+ my $unit = $_;
402+ my $baseUnit = $unit;
403+ my $newUnitFile = "$out/etc/systemd/system/$baseUnit";
404405+ # Detect template instances.
406+ if (!-e $newUnitFile && $unit =~ /^(.*)@[^\.]*\.(.*)$/) {
407+ $baseUnit = "$1\@.$2";
408+ $newUnitFile = "$out/etc/systemd/system/$baseUnit";
409+ }
410+411+ my $baseName = $baseUnit;
412+ $baseName =~ s/\.[a-z]*$//;
413+414+ # Start units if they were not active previously
415+ if (not defined $activePrev->{$unit}) {
416+ $unitsToStart{$unit} = 1;
417+ next;
418+ }
419+420+ handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToRestart, \%unitsToRestart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
421+ }
422+ unlink($dryRestartByActivationFile);
423424 print STDERR "would restart systemd\n" if $restartSystemd;
425 print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n"
426 if scalar(keys %unitsToReload) > 0;
427 print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n"
428 if scalar(keys %unitsToRestart) > 0;
429+ my @unitsToStartFiltered = filterUnits(\%unitsToStart);
430 print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n"
431 if scalar @unitsToStartFiltered;
00432 exit 0;
433}
434···452system("$out/activate", "$out") == 0 or $res = 2;
453454# Handle the activation script requesting the restart or reload of a unit.
455+foreach (split('\n', read_file($restartByActivationFile, err_mode => 'quiet') // "")) {
456+ my $unit = $_;
457+ my $baseUnit = $unit;
458+ my $newUnitFile = "$out/etc/systemd/system/$baseUnit";
459460+ # Detect template instances.
461+ if (!-e $newUnitFile && $unit =~ /^(.*)@[^\.]*\.(.*)$/) {
462+ $baseUnit = "$1\@.$2";
463+ $newUnitFile = "$out/etc/systemd/system/$baseUnit";
464+ }
465+466+ my $baseName = $baseUnit;
467+ $baseName =~ s/\.[a-z]*$//;
468+469+ # Start units if they were not active previously
470+ if (not defined $activePrev->{$unit}) {
471+ $unitsToStart{$unit} = 1;
472+ recordUnit($startListFile, $unit);
473+ next;
474+ }
475+476+ handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToRestart, \%unitsToRestart, \%unitsToReload, \%unitsToRestart, \%unitsToSkip);
477+}
478+# We can remove the file now because it has been propagated to the other restart/reload files
479+unlink($restartByActivationFile);
480481# Restart systemd if necessary. Note that this is done using the
482# current version of systemd, just in case the new one has trouble
···517 print STDERR "reloading the following units: ", join(", ", sort(keys %unitsToReload)), "\n";
518 system("@systemd@/bin/systemctl", "reload", "--", sort(keys %unitsToReload)) == 0 or $res = 4;
519 unlink($reloadListFile);
0520}
521522# Restart changed services (those that have to be restarted rather
···525 print STDERR "restarting the following units: ", join(", ", sort(keys %unitsToRestart)), "\n";
526 system("@systemd@/bin/systemctl", "restart", "--", sort(keys %unitsToRestart)) == 0 or $res = 4;
527 unlink($restartListFile);
0528}
529530# Start all active targets, as well as changed units we stopped above.
···533# that are symlinks to other units. We shouldn't start both at the
534# same time because we'll get a "Failed to add path to set" error from
535# systemd.
536+my @unitsToStartFiltered = filterUnits(\%unitsToStart);
537print STDERR "starting the following units: ", join(", ", @unitsToStartFiltered), "\n"
538 if scalar @unitsToStartFiltered;
539system("@systemd@/bin/systemctl", "start", "--", sort(keys %unitsToStart)) == 0 or $res = 4;