···15681568 encapsulation.
15691569 </para>
15701570 </listitem>
15711571+ <listitem>
15721572+ <para>
15731573+ Changing systemd <literal>.socket</literal> units now restarts
15741574+ them and stops the service that is activated by them.
15751575+ Additionally, services with
15761576+ <literal>stopOnChange = false</literal> don’t break anymore
15771577+ when they are socket-activated.
15781578+ </para>
15791579+ </listitem>
15711580 </itemizedlist>
15721581 </section>
15731582</section>
+2
nixos/doc/manual/release-notes/rl-2111.section.md
···453453- The `networking` module has a new `networking.fooOverUDP` option to configure Foo-over-UDP encapsulations.
454454455455- `networking.sits` now supports Foo-over-UDP encapsulation.
456456+457457+- Changing systemd `.socket` units now restarts them and stops the service that is activated by them. Additionally, services with `stopOnChange = false` don't break anymore when they are socket-activated.
···11111212my $out = "@out@";
13131414-# FIXME: maybe we should use /proc/1/exe to get the current systemd.
1514my $curSystemd = abs_path("/run/current-system/sw/bin");
16151716# To be robust against interruption, record what units need to be started etc.
···1918my $restartListFile = "/run/nixos/restart-list";
2019my $reloadListFile = "/run/nixos/reload-list";
21202222-# Parse restart/reload requests by the activation script
2121+# Parse restart/reload requests by the activation script.
2222+# Activation scripts may write newline-separated units to this
2323+# file and switch-to-configuration will handle them. While
2424+# `stopIfChanged = true` is ignored, switch-to-configuration will
2525+# handle `restartIfChanged = false` and `reloadIfChanged = true`.
2626+# This also works for socket-activated units.
2327my $restartByActivationFile = "/run/nixos/activation-restart-list";
2424-my $reloadByActivationFile = "/run/nixos/activation-reload-list";
2528my $dryRestartByActivationFile = "/run/nixos/dry-activation-restart-list";
2626-my $dryReloadByActivationFile = "/run/nixos/dry-activation-reload-list";
27292828-make_path("/run/nixos", { mode => 0755 });
3030+make_path("/run/nixos", { mode => oct(755) });
29313032my $action = shift @ARGV;
3133···147149 return abs_path($s) . (-f "${s}.d/overrides.conf" ? " " . abs_path "${s}.d/overrides.conf" : "");
148150}
149151152152+sub handleModifiedUnit {
153153+ my ($unit, $baseName, $newUnitFile, $activePrev, $unitsToStop, $unitsToStart, $unitsToReload, $unitsToRestart, $unitsToSkip) = @_;
154154+155155+ if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target" || $unit =~ /\.slice$/ || $unit =~ /\.path$/) {
156156+ # Do nothing. These cannot be restarted directly.
157157+ # Slices and Paths don't have to be restarted since
158158+ # properties (resource limits and inotify watches)
159159+ # seem to get applied on daemon-reload.
160160+ } elsif ($unit =~ /\.mount$/) {
161161+ # Reload the changed mount unit to force a remount.
162162+ $unitsToReload->{$unit} = 1;
163163+ recordUnit($reloadListFile, $unit);
164164+ } else {
165165+ my $unitInfo = parseUnit($newUnitFile);
166166+ if (boolIsTrue($unitInfo->{'X-ReloadIfChanged'} // "no")) {
167167+ $unitsToReload->{$unit} = 1;
168168+ recordUnit($reloadListFile, $unit);
169169+ }
170170+ elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
171171+ $unitsToSkip->{$unit} = 1;
172172+ } else {
173173+ # If this unit is socket-activated, then stop it instead
174174+ # of restarting it to make sure the new version of it is
175175+ # socket-activated.
176176+ my $socketActivated = 0;
177177+ if ($unit =~ /\.service$/) {
178178+ my @sockets = split / /, ($unitInfo->{Sockets} // "");
179179+ if (scalar @sockets == 0) {
180180+ @sockets = ("$baseName.socket");
181181+ }
182182+ foreach my $socket (@sockets) {
183183+ if (-e "$out/etc/systemd/system/$socket") {
184184+ $socketActivated = 1;
185185+ $unitsToStop->{$unit} = 1;
186186+ # If the socket was not running previously,
187187+ # start it now.
188188+ if (not defined $activePrev->{$socket}) {
189189+ $unitsToStart->{$socket} = 1;
190190+ }
191191+ }
192192+ }
193193+ }
194194+195195+ # Don't do the rest of this for socket-activated units
196196+ # because we handled these above where we stop the unit.
197197+ # Since only services can be socket-activated, the
198198+ # following condition always evaluates to `true` for
199199+ # non-service units.
200200+ if ($socketActivated) {
201201+ return;
202202+ }
203203+204204+ # If we are restarting a socket, also stop the corresponding
205205+ # service. This is required because restarting a socket
206206+ # when the service is already activated fails.
207207+ if ($unit =~ /\.socket$/) {
208208+ my $service = $unitInfo->{Service} // "";
209209+ if ($service eq "") {
210210+ $service = "$baseName.service";
211211+ }
212212+ if (defined $activePrev->{$service}) {
213213+ $unitsToStop->{$service} = 1;
214214+ }
215215+ $unitsToRestart->{$unit} = 1;
216216+ recordUnit($restartListFile, $unit);
217217+ } else {
218218+ # Always restart non-services instead of stopping and starting them
219219+ # because it doesn't make sense to stop them with a config from
220220+ # the old evaluation.
221221+ if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes") || $unit !~ /\.service$/) {
222222+ # This unit should be restarted instead of
223223+ # stopped and started.
224224+ $unitsToRestart->{$unit} = 1;
225225+ recordUnit($restartListFile, $unit);
226226+ } else {
227227+ # We write to a file to ensure that the
228228+ # service gets restarted if we're interrupted.
229229+ $unitsToStart->{$unit} = 1;
230230+ recordUnit($startListFile, $unit);
231231+ $unitsToStop->{$unit} = 1;
232232+ }
233233+ }
234234+ }
235235+ }
236236+}
237237+150238# Figure out what units need to be stopped, started, restarted or reloaded.
151239my (%unitsToStop, %unitsToSkip, %unitsToStart, %unitsToRestart, %unitsToReload);
152240···219307 }
220308221309 elsif (fingerprintUnit($prevUnitFile) ne fingerprintUnit($newUnitFile)) {
222222- if ($unit eq "sysinit.target" || $unit eq "basic.target" || $unit eq "multi-user.target" || $unit eq "graphical.target") {
223223- # Do nothing. These cannot be restarted directly.
224224- } elsif ($unit =~ /\.mount$/) {
225225- # Reload the changed mount unit to force a remount.
226226- $unitsToReload{$unit} = 1;
227227- recordUnit($reloadListFile, $unit);
228228- } elsif ($unit =~ /\.socket$/ || $unit =~ /\.path$/ || $unit =~ /\.slice$/) {
229229- # FIXME: do something?
230230- } else {
231231- my $unitInfo = parseUnit($newUnitFile);
232232- if (boolIsTrue($unitInfo->{'X-ReloadIfChanged'} // "no")) {
233233- $unitsToReload{$unit} = 1;
234234- recordUnit($reloadListFile, $unit);
235235- }
236236- elsif (!boolIsTrue($unitInfo->{'X-RestartIfChanged'} // "yes") || boolIsTrue($unitInfo->{'RefuseManualStop'} // "no") || boolIsTrue($unitInfo->{'X-OnlyManualStart'} // "no")) {
237237- $unitsToSkip{$unit} = 1;
238238- } else {
239239- if (!boolIsTrue($unitInfo->{'X-StopIfChanged'} // "yes")) {
240240- # This unit should be restarted instead of
241241- # stopped and started.
242242- $unitsToRestart{$unit} = 1;
243243- recordUnit($restartListFile, $unit);
244244- } else {
245245- # If this unit is socket-activated, then stop the
246246- # socket unit(s) as well, and restart the
247247- # socket(s) instead of the service.
248248- my $socketActivated = 0;
249249- if ($unit =~ /\.service$/) {
250250- my @sockets = split / /, ($unitInfo->{Sockets} // "");
251251- if (scalar @sockets == 0) {
252252- @sockets = ("$baseName.socket");
253253- }
254254- foreach my $socket (@sockets) {
255255- if (defined $activePrev->{$socket}) {
256256- $unitsToStop{$socket} = 1;
257257- # Only restart sockets that actually
258258- # exist in new configuration:
259259- if (-e "$out/etc/systemd/system/$socket") {
260260- $unitsToStart{$socket} = 1;
261261- recordUnit($startListFile, $socket);
262262- $socketActivated = 1;
263263- }
264264- }
265265- }
266266- }
267267-268268- # If the unit is not socket-activated, record
269269- # that this unit needs to be started below.
270270- # We write this to a file to ensure that the
271271- # service gets restarted if we're interrupted.
272272- if (!$socketActivated) {
273273- $unitsToStart{$unit} = 1;
274274- recordUnit($startListFile, $unit);
275275- }
276276-277277- $unitsToStop{$unit} = 1;
278278- }
279279- }
280280- }
310310+ handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, %unitsToSkip);
281311 }
282312 }
283313}
···362392}
363393364394my @unitsToStopFiltered = filterUnits(\%unitsToStop);
365365-my @unitsToStartFiltered = filterUnits(\%unitsToStart);
366366-367395368396# Show dry-run actions.
369397if ($action eq "dry-activate") {
···375403 print STDERR "would activate the configuration...\n";
376404 system("$out/dry-activate", "$out");
377405378378- $unitsToRestart{$_} = 1 foreach
379379- split('\n', read_file($dryRestartByActivationFile, err_mode => 'quiet') // "");
406406+ # Handle the activation script requesting the restart or reload of a unit.
407407+ my %unitsToAlsoStop;
408408+ my %unitsToAlsoSkip;
409409+ foreach (split('\n', read_file($dryRestartByActivationFile, err_mode => 'quiet') // "")) {
410410+ my $unit = $_;
411411+ my $baseUnit = $unit;
412412+ my $newUnitFile = "$out/etc/systemd/system/$baseUnit";
380413381381- $unitsToReload{$_} = 1 foreach
382382- split('\n', read_file($dryReloadByActivationFile, err_mode => 'quiet') // "");
414414+ # Detect template instances.
415415+ if (!-e $newUnitFile && $unit =~ /^(.*)@[^\.]*\.(.*)$/) {
416416+ $baseUnit = "$1\@.$2";
417417+ $newUnitFile = "$out/etc/systemd/system/$baseUnit";
418418+ }
419419+420420+ my $baseName = $baseUnit;
421421+ $baseName =~ s/\.[a-z]*$//;
422422+423423+ handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToAlsoStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, %unitsToAlsoSkip);
424424+ }
425425+ unlink($dryRestartByActivationFile);
426426+427427+ my @unitsToAlsoStopFiltered = filterUnits(\%unitsToAlsoStop);
428428+ if (scalar(keys %unitsToAlsoStop) > 0) {
429429+ print STDERR "would stop the following units as well: ", join(", ", @unitsToAlsoStopFiltered), "\n"
430430+ if scalar @unitsToAlsoStopFiltered;
431431+ }
432432+433433+ print STDERR "would NOT restart the following changed units as well: ", join(", ", sort(keys %unitsToAlsoSkip)), "\n"
434434+ if scalar(keys %unitsToAlsoSkip) > 0;
383435384436 print STDERR "would restart systemd\n" if $restartSystemd;
437437+ print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n"
438438+ if scalar(keys %unitsToReload) > 0;
385439 print STDERR "would restart the following units: ", join(", ", sort(keys %unitsToRestart)), "\n"
386440 if scalar(keys %unitsToRestart) > 0;
441441+ my @unitsToStartFiltered = filterUnits(\%unitsToStart);
387442 print STDERR "would start the following units: ", join(", ", @unitsToStartFiltered), "\n"
388443 if scalar @unitsToStartFiltered;
389389- print STDERR "would reload the following units: ", join(", ", sort(keys %unitsToReload)), "\n"
390390- if scalar(keys %unitsToReload) > 0;
391391- unlink($dryRestartByActivationFile);
392392- unlink($dryReloadByActivationFile);
393444 exit 0;
394445}
395446···400451 print STDERR "stopping the following units: ", join(", ", @unitsToStopFiltered), "\n"
401452 if scalar @unitsToStopFiltered;
402453 # Use current version of systemctl binary before daemon is reexeced.
403403- system("$curSystemd/systemctl", "stop", "--", sort(keys %unitsToStop)); # FIXME: ignore errors?
454454+ system("$curSystemd/systemctl", "stop", "--", sort(keys %unitsToStop));
404455}
405456406457print STDERR "NOT restarting the following changed units: ", join(", ", sort(keys %unitsToSkip)), "\n"
···414465415466# Handle the activation script requesting the restart or reload of a unit.
416467# We can only restart and reload (not stop/start) because the units to be
417417-# stopped are already stopped before the activation script is run.
418418-$unitsToRestart{$_} = 1 foreach
419419- split('\n', read_file($restartByActivationFile, err_mode => 'quiet') // "");
468468+# stopped are already stopped before the activation script is run. We do however
469469+# make an exception for services that are socket-activated and that have to be stopped
470470+# instead of being restarted.
471471+my %unitsToAlsoStop;
472472+my %unitsToAlsoSkip;
473473+foreach (split('\n', read_file($restartByActivationFile, err_mode => 'quiet') // "")) {
474474+ my $unit = $_;
475475+ my $baseUnit = $unit;
476476+ my $newUnitFile = "$out/etc/systemd/system/$baseUnit";
477477+478478+ # Detect template instances.
479479+ if (!-e $newUnitFile && $unit =~ /^(.*)@[^\.]*\.(.*)$/) {
480480+ $baseUnit = "$1\@.$2";
481481+ $newUnitFile = "$out/etc/systemd/system/$baseUnit";
482482+ }
483483+484484+ my $baseName = $baseUnit;
485485+ $baseName =~ s/\.[a-z]*$//;
486486+487487+ handleModifiedUnit($unit, $baseName, $newUnitFile, $activePrev, \%unitsToAlsoStop, \%unitsToStart, \%unitsToReload, \%unitsToRestart, %unitsToAlsoSkip);
488488+}
489489+unlink($restartByActivationFile);
490490+491491+my @unitsToAlsoStopFiltered = filterUnits(\%unitsToAlsoStop);
492492+if (scalar(keys %unitsToAlsoStop) > 0) {
493493+ print STDERR "stopping the following units as well: ", join(", ", @unitsToAlsoStopFiltered), "\n"
494494+ if scalar @unitsToAlsoStopFiltered;
495495+ system("$curSystemd/systemctl", "stop", "--", sort(keys %unitsToAlsoStop));
496496+}
420497421421-$unitsToReload{$_} = 1 foreach
422422- split('\n', read_file($reloadByActivationFile, err_mode => 'quiet') // "");
498498+print STDERR "NOT restarting the following changed units as well: ", join(", ", sort(keys %unitsToAlsoSkip)), "\n"
499499+ if scalar(keys %unitsToAlsoSkip) > 0;
423500424501# Restart systemd if necessary. Note that this is done using the
425502# current version of systemd, just in case the new one has trouble
···460537 print STDERR "reloading the following units: ", join(", ", sort(keys %unitsToReload)), "\n";
461538 system("@systemd@/bin/systemctl", "reload", "--", sort(keys %unitsToReload)) == 0 or $res = 4;
462539 unlink($reloadListFile);
463463- unlink($reloadByActivationFile);
464540}
465541466542# Restart changed services (those that have to be restarted rather
467543# than stopped and started).
468544if (scalar(keys %unitsToRestart) > 0) {
469545 print STDERR "restarting the following units: ", join(", ", sort(keys %unitsToRestart)), "\n";
470470- system("@systemd@/bin/systemctl", "restart", "--", sort(keys %unitsToRestart)) == 0 or $res = 4;
546546+547547+ # We split the units to be restarted into sockets and non-sockets.
548548+ # This is because restarting sockets may fail which is not bad by
549549+ # itself but which will prevent changes on the sockets. We usually
550550+ # restart the socket and stop the service before that. Restarting
551551+ # the socket will fail however when the service was re-activated
552552+ # in the meantime. There is no proper way to prevent that from happening.
553553+ my @unitsWithErrorHandling = grep { $_ !~ /\.socket$/ } sort(keys %unitsToRestart);
554554+ my @unitsWithoutErrorHandling = grep { $_ =~ /\.socket$/ } sort(keys %unitsToRestart);
555555+556556+ if (scalar(@unitsWithErrorHandling) > 0) {
557557+ system("@systemd@/bin/systemctl", "restart", "--", @unitsWithErrorHandling) == 0 or $res = 4;
558558+ }
559559+ if (scalar(@unitsWithoutErrorHandling) > 0) {
560560+ # Don't print warnings from systemctl
561561+ no warnings 'once';
562562+ open(OLDERR, ">&", \*STDERR);
563563+ close(STDERR);
564564+565565+ my $ret = system("@systemd@/bin/systemctl", "restart", "--", @unitsWithoutErrorHandling);
566566+567567+ # Print stderr again
568568+ open(STDERR, ">&OLDERR");
569569+570570+ if ($ret ne 0) {
571571+ print STDERR "warning: some sockets failed to restart. Please check your journal (journalctl -eb) and act accordingly.\n";
572572+ }
573573+ }
471574 unlink($restartListFile);
472575 unlink($restartByActivationFile);
473576}
···478581# that are symlinks to other units. We shouldn't start both at the
479582# same time because we'll get a "Failed to add path to set" error from
480583# systemd.
584584+my @unitsToStartFiltered = filterUnits(\%unitsToStart);
481585print STDERR "starting the following units: ", join(", ", @unitsToStartFiltered), "\n"
482586 if scalar @unitsToStartFiltered;
483587system("@systemd@/bin/systemctl", "start", "--", sort(keys %unitsToStart)) == 0 or $res = 4;
···485589486590487591# Print failed and new units.
488488-my (@failed, @new, @restarting);
592592+my (@failed, @new);
489593my $activeNew = getActiveUnits;
490594while (my ($unit, $state) = each %{$activeNew}) {
491595 if ($state->{state} eq "failed") {
···501605 push @failed, $unit;
502606 }
503607 }
504504- elsif ($state->{state} ne "failed" && !defined $activePrev->{$unit}) {
608608+ # Ignore scopes since they are not managed by this script but rather
609609+ # created and managed by third-party services via the systemd dbus API.
610610+ elsif ($state->{state} ne "failed" && !defined $activePrev->{$unit} && $unit !~ /\.scope$/) {
505611 push @new, $unit;
506612 }
507613}
+7
nixos/modules/system/activation/top-level.nix
···8484 export localeArchive="${config.i18n.glibcLocales}/lib/locale/locale-archive"
8585 substituteAll ${./switch-to-configuration.pl} $out/bin/switch-to-configuration
8686 chmod +x $out/bin/switch-to-configuration
8787+ ${optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) ''
8888+ if ! output=$($perl/bin/perl -c $out/bin/switch-to-configuration 2>&1); then
8989+ echo "switch-to-configuration syntax is not valid:"
9090+ echo "$output"
9191+ exit 1
9292+ fi
9393+ ''}
87948895 echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies
8996
+382-3
nixos/tests/switch-test.nix
···77 };
8899 nodes = {
1010- machine = { ... }: {
1010+ machine = { config, pkgs, lib, ... }: {
1111+ environment.systemPackages = [ pkgs.socat ]; # for the socket activation stuff
1112 users.mutableUsers = false;
1313+1414+ specialisation = {
1515+ # A system with a simple socket-activated unit
1616+ simple-socket.configuration = {
1717+ systemd.services.socket-activated.serviceConfig = {
1818+ ExecStart = pkgs.writeScript "socket-test.py" /* python */ ''
1919+ #!${pkgs.python3}/bin/python3
2020+2121+ from socketserver import TCPServer, StreamRequestHandler
2222+ import socket
2323+2424+ class Handler(StreamRequestHandler):
2525+ def handle(self):
2626+ self.wfile.write("hello".encode("utf-8"))
2727+2828+ class Server(TCPServer):
2929+ def __init__(self, server_address, handler_cls):
3030+ # Invoke base but omit bind/listen steps (performed by systemd activation!)
3131+ TCPServer.__init__(
3232+ self, server_address, handler_cls, bind_and_activate=False)
3333+ # Override socket
3434+ self.socket = socket.fromfd(3, self.address_family, self.socket_type)
3535+3636+ if __name__ == "__main__":
3737+ server = Server(("localhost", 1234), Handler)
3838+ server.serve_forever()
3939+ '';
4040+ };
4141+ systemd.sockets.socket-activated = {
4242+ wantedBy = [ "sockets.target" ];
4343+ listenStreams = [ "/run/test.sock" ];
4444+ socketConfig.SocketMode = lib.mkDefault "0777";
4545+ };
4646+ };
4747+4848+ # The same system but the socket is modified
4949+ modified-socket.configuration = {
5050+ imports = [ config.specialisation.simple-socket.configuration ];
5151+ systemd.sockets.socket-activated.socketConfig.SocketMode = "0666";
5252+ };
5353+5454+ # The same system but the service is modified
5555+ modified-service.configuration = {
5656+ imports = [ config.specialisation.simple-socket.configuration ];
5757+ systemd.services.socket-activated.serviceConfig.X-Test = "test";
5858+ };
5959+6060+ # The same system but both service and socket are modified
6161+ modified-service-and-socket.configuration = {
6262+ imports = [ config.specialisation.simple-socket.configuration ];
6363+ systemd.services.socket-activated.serviceConfig.X-Test = "some_value";
6464+ systemd.sockets.socket-activated.socketConfig.SocketMode = "0444";
6565+ };
6666+6767+ # A system with a socket-activated service and some simple services
6868+ service-and-socket.configuration = {
6969+ imports = [ config.specialisation.simple-socket.configuration ];
7070+ systemd.services.simple-service = {
7171+ wantedBy = [ "multi-user.target" ];
7272+ serviceConfig = {
7373+ Type = "oneshot";
7474+ RemainAfterExit = true;
7575+ ExecStart = "${pkgs.coreutils}/bin/true";
7676+ };
7777+ };
7878+7979+ systemd.services.simple-restart-service = {
8080+ stopIfChanged = false;
8181+ wantedBy = [ "multi-user.target" ];
8282+ serviceConfig = {
8383+ Type = "oneshot";
8484+ RemainAfterExit = true;
8585+ ExecStart = "${pkgs.coreutils}/bin/true";
8686+ };
8787+ };
8888+8989+ systemd.services.simple-reload-service = {
9090+ reloadIfChanged = true;
9191+ wantedBy = [ "multi-user.target" ];
9292+ serviceConfig = {
9393+ Type = "oneshot";
9494+ RemainAfterExit = true;
9595+ ExecStart = "${pkgs.coreutils}/bin/true";
9696+ ExecReload = "${pkgs.coreutils}/bin/true";
9797+ };
9898+ };
9999+100100+ systemd.services.no-restart-service = {
101101+ restartIfChanged = false;
102102+ wantedBy = [ "multi-user.target" ];
103103+ serviceConfig = {
104104+ Type = "oneshot";
105105+ RemainAfterExit = true;
106106+ ExecStart = "${pkgs.coreutils}/bin/true";
107107+ };
108108+ };
109109+ };
110110+111111+ # The same system but with an activation script that restarts all services
112112+ restart-and-reload-by-activation-script.configuration = {
113113+ imports = [ config.specialisation.service-and-socket.configuration ];
114114+ system.activationScripts.restart-and-reload-test = {
115115+ supportsDryActivation = true;
116116+ deps = [];
117117+ text = ''
118118+ if [ "$NIXOS_ACTION" = dry-activate ]; then
119119+ f=/run/nixos/dry-activation-restart-list
120120+ else
121121+ f=/run/nixos/activation-restart-list
122122+ fi
123123+ cat <<EOF >> "$f"
124124+ simple-service.service
125125+ simple-restart-service.service
126126+ simple-reload-service.service
127127+ no-restart-service.service
128128+ socket-activated.service
129129+ EOF
130130+ '';
131131+ };
132132+ };
133133+134134+ # A system with a timer
135135+ with-timer.configuration = {
136136+ systemd.timers.test-timer = {
137137+ wantedBy = [ "timers.target" ];
138138+ timerConfig.OnCalendar = "@1395716396"; # chosen by fair dice roll
139139+ };
140140+ systemd.services.test-timer = {
141141+ serviceConfig = {
142142+ Type = "oneshot";
143143+ ExecStart = "${pkgs.coreutils}/bin/true";
144144+ };
145145+ };
146146+ };
147147+148148+ # The same system but with another time
149149+ with-timer-modified.configuration = {
150150+ imports = [ config.specialisation.with-timer.configuration ];
151151+ systemd.timers.test-timer.timerConfig.OnCalendar = lib.mkForce "Fri 2012-11-23 16:00:00";
152152+ };
153153+154154+ # A system with a systemd mount
155155+ with-mount.configuration = {
156156+ systemd.mounts = [
157157+ {
158158+ description = "Testmount";
159159+ what = "tmpfs";
160160+ type = "tmpfs";
161161+ where = "/testmount";
162162+ options = "size=1M";
163163+ wantedBy = [ "local-fs.target" ];
164164+ }
165165+ ];
166166+ };
167167+168168+ # The same system but with another time
169169+ with-mount-modified.configuration = {
170170+ systemd.mounts = [
171171+ {
172172+ description = "Testmount";
173173+ what = "tmpfs";
174174+ type = "tmpfs";
175175+ where = "/testmount";
176176+ options = "size=10M";
177177+ wantedBy = [ "local-fs.target" ];
178178+ }
179179+ ];
180180+ };
181181+182182+ # A system with a path unit
183183+ with-path.configuration = {
184184+ systemd.paths.test-watch = {
185185+ wantedBy = [ "paths.target" ];
186186+ pathConfig.PathExists = "/testpath";
187187+ };
188188+ systemd.services.test-watch = {
189189+ serviceConfig = {
190190+ Type = "oneshot";
191191+ ExecStart = "${pkgs.coreutils}/bin/touch /testpath-modified";
192192+ };
193193+ };
194194+ };
195195+196196+ # The same system but watching another file
197197+ with-path-modified.configuration = {
198198+ imports = [ config.specialisation.with-path.configuration ];
199199+ systemd.paths.test-watch.pathConfig.PathExists = lib.mkForce "/testpath2";
200200+ };
201201+202202+ # A system with a slice
203203+ with-slice.configuration = {
204204+ systemd.slices.testslice.sliceConfig.MemoryMax = "1"; # don't allow memory allocation
205205+ systemd.services.testservice = {
206206+ serviceConfig = {
207207+ Type = "oneshot";
208208+ RemainAfterExit = true;
209209+ ExecStart = "${pkgs.coreutils}/bin/true";
210210+ Slice = "testslice.slice";
211211+ };
212212+ };
213213+ };
214214+215215+ # The same system but the slice allows to allocate memory
216216+ with-slice-non-crashing.configuration = {
217217+ imports = [ config.specialisation.with-slice.configuration ];
218218+ systemd.slices.testslice.sliceConfig.MemoryMax = lib.mkForce null;
219219+ };
220220+ };
12221 };
13222 other = { ... }: {
14223 users.mutableUsers = true;
15224 };
16225 };
172261818- testScript = {nodes, ...}: let
227227+ testScript = { nodes, ... }: let
19228 originalSystem = nodes.machine.config.system.build.toplevel;
20229 otherSystem = nodes.other.config.system.build.toplevel;
21230···27236 set -o pipefail
28237 exec env -i "$@" | tee /dev/stderr
29238 '';
3030- in ''
239239+ in /* python */ ''
240240+ def switch_to_specialisation(name, action="test"):
241241+ out = machine.succeed(f"${originalSystem}/specialisation/{name}/bin/switch-to-configuration {action} 2>&1")
242242+ assert_lacks(out, "switch-to-configuration line") # Perl warnings
243243+ return out
244244+245245+ def assert_contains(haystack, needle):
246246+ if needle not in haystack:
247247+ print("The haystack that will cause the following exception is:")
248248+ print("---")
249249+ print(haystack)
250250+ print("---")
251251+ raise Exception(f"Expected string '{needle}' was not found")
252252+253253+ def assert_lacks(haystack, needle):
254254+ if needle in haystack:
255255+ print("The haystack that will cause the following exception is:")
256256+ print("---")
257257+ print(haystack, end="")
258258+ print("---")
259259+ raise Exception(f"Unexpected string '{needle}' was found")
260260+261261+31262 machine.succeed(
32263 "${stderrRunner} ${originalSystem}/bin/switch-to-configuration test"
33264 )
34265 machine.succeed(
35266 "${stderrRunner} ${otherSystem}/bin/switch-to-configuration test"
36267 )
268268+269269+ with subtest("systemd sockets"):
270270+ machine.succeed("${originalSystem}/bin/switch-to-configuration test")
271271+272272+ # Simple socket is created
273273+ out = switch_to_specialisation("simple-socket")
274274+ assert_lacks(out, "stopping the following units:")
275275+ # not checking for reload because dbus gets reloaded
276276+ assert_lacks(out, "restarting the following units:")
277277+ assert_lacks(out, "\nstarting the following units:")
278278+ assert_contains(out, "the following new units were started: socket-activated.socket\n")
279279+ assert_lacks(out, "as well:")
280280+ machine.succeed("[ $(stat -c%a /run/test.sock) = 777 ]")
281281+282282+ # Changing the socket restarts it
283283+ out = switch_to_specialisation("modified-socket")
284284+ assert_lacks(out, "stopping the following units:")
285285+ #assert_lacks(out, "reloading the following units:")
286286+ assert_contains(out, "restarting the following units: socket-activated.socket\n")
287287+ assert_lacks(out, "\nstarting the following units:")
288288+ assert_lacks(out, "the following new units were started:")
289289+ assert_lacks(out, "as well:")
290290+ machine.succeed("[ $(stat -c%a /run/test.sock) = 666 ]") # change was applied
291291+292292+ # The unit is properly activated when the socket is accessed
293293+ if machine.succeed("socat - UNIX-CONNECT:/run/test.sock") != "hello":
294294+ raise Exception("Socket was not properly activated")
295295+296296+ # Changing the socket restarts it and ignores the active service
297297+ out = switch_to_specialisation("simple-socket")
298298+ assert_contains(out, "stopping the following units: socket-activated.service\n")
299299+ assert_lacks(out, "reloading the following units:")
300300+ assert_contains(out, "restarting the following units: socket-activated.socket\n")
301301+ assert_lacks(out, "\nstarting the following units:")
302302+ assert_lacks(out, "the following new units were started:")
303303+ assert_lacks(out, "as well:")
304304+ machine.succeed("[ $(stat -c%a /run/test.sock) = 777 ]") # change was applied
305305+306306+ # Changing the service does nothing when the service is not active
307307+ out = switch_to_specialisation("modified-service")
308308+ assert_lacks(out, "stopping the following units:")
309309+ assert_lacks(out, "reloading the following units:")
310310+ assert_lacks(out, "restarting the following units:")
311311+ assert_lacks(out, "\nstarting the following units:")
312312+ assert_lacks(out, "the following new units were started:")
313313+ assert_lacks(out, "as well:")
314314+315315+ # Activating the service and modifying it stops it but leaves the socket untouched
316316+ machine.succeed("socat - UNIX-CONNECT:/run/test.sock")
317317+ out = switch_to_specialisation("simple-socket")
318318+ assert_contains(out, "stopping the following units: socket-activated.service\n")
319319+ assert_lacks(out, "reloading the following units:")
320320+ assert_lacks(out, "restarting the following units:")
321321+ assert_lacks(out, "\nstarting the following units:")
322322+ assert_lacks(out, "the following new units were started:")
323323+ assert_lacks(out, "as well:")
324324+325325+ # Activating the service and both the service and the socket stops the service and restarts the socket
326326+ machine.succeed("socat - UNIX-CONNECT:/run/test.sock")
327327+ out = switch_to_specialisation("modified-service-and-socket")
328328+ assert_contains(out, "stopping the following units: socket-activated.service\n")
329329+ assert_lacks(out, "reloading the following units:")
330330+ assert_contains(out, "restarting the following units: socket-activated.socket\n")
331331+ assert_lacks(out, "\nstarting the following units:")
332332+ assert_lacks(out, "the following new units were started:")
333333+ assert_lacks(out, "as well:")
334334+335335+ with subtest("restart and reload by activation file"):
336336+ out = switch_to_specialisation("service-and-socket")
337337+ # Switch to a system where the example services get restarted
338338+ # by the activation script
339339+ out = switch_to_specialisation("restart-and-reload-by-activation-script")
340340+ assert_lacks(out, "stopping the following units:")
341341+ assert_contains(out, "stopping the following units as well: simple-service.service, socket-activated.service\n")
342342+ assert_contains(out, "reloading the following units: simple-reload-service.service\n")
343343+ assert_contains(out, "restarting the following units: simple-restart-service.service\n")
344344+ assert_contains(out, "\nstarting the following units: simple-service.service")
345345+346346+ # The same, but in dry mode
347347+ switch_to_specialisation("service-and-socket")
348348+ out = switch_to_specialisation("restart-and-reload-by-activation-script", action="dry-activate")
349349+ assert_lacks(out, "would stop the following units:")
350350+ assert_contains(out, "would stop the following units as well: simple-service.service, socket-activated.service\n")
351351+ assert_contains(out, "would reload the following units: simple-reload-service.service\n")
352352+ assert_contains(out, "would restart the following units: simple-restart-service.service\n")
353353+ assert_contains(out, "\nwould start the following units: simple-service.service")
354354+355355+ with subtest("mounts"):
356356+ switch_to_specialisation("with-mount")
357357+ out = machine.succeed("mount | grep 'on /testmount'")
358358+ assert_contains(out, "size=1024k")
359359+360360+ out = switch_to_specialisation("with-mount-modified")
361361+ assert_lacks(out, "stopping the following units:")
362362+ assert_contains(out, "reloading the following units: testmount.mount\n")
363363+ assert_lacks(out, "restarting the following units:")
364364+ assert_lacks(out, "\nstarting the following units:")
365365+ assert_lacks(out, "the following new units were started:")
366366+ assert_lacks(out, "as well:")
367367+ # It changed
368368+ out = machine.succeed("mount | grep 'on /testmount'")
369369+ assert_contains(out, "size=10240k")
370370+371371+ with subtest("timers"):
372372+ switch_to_specialisation("with-timer")
373373+ out = machine.succeed("systemctl show test-timer.timer")
374374+ assert_contains(out, "OnCalendar=2014-03-25 02:59:56 UTC")
375375+376376+ out = switch_to_specialisation("with-timer-modified")
377377+ assert_lacks(out, "stopping the following units:")
378378+ assert_lacks(out, "reloading the following units:")
379379+ assert_contains(out, "restarting the following units: test-timer.timer\n")
380380+ assert_lacks(out, "\nstarting the following units:")
381381+ assert_lacks(out, "the following new units were started:")
382382+ assert_lacks(out, "as well:")
383383+ # It changed
384384+ out = machine.succeed("systemctl show test-timer.timer")
385385+ assert_contains(out, "OnCalendar=Fri 2012-11-23 16:00:00")
386386+387387+ with subtest("paths"):
388388+ switch_to_specialisation("with-path")
389389+ machine.fail("test -f /testpath-modified")
390390+391391+ # touch the file, unit should be triggered
392392+ machine.succeed("touch /testpath")
393393+ machine.wait_until_succeeds("test -f /testpath-modified")
394394+395395+ machine.succeed("rm /testpath /testpath-modified")
396396+ switch_to_specialisation("with-path-modified")
397397+398398+ machine.succeed("touch /testpath")
399399+ machine.fail("test -f /testpath-modified")
400400+ machine.succeed("touch /testpath2")
401401+ machine.wait_until_succeeds("test -f /testpath-modified")
402402+403403+ # This test ensures that changes to slice configuration get applied.
404404+ # We test this by having a slice that allows no memory allocation at
405405+ # all and starting a service within it. If the service crashes, the slice
406406+ # is applied and if we modify the slice to allow memory allocation, the
407407+ # service should successfully start.
408408+ with subtest("slices"):
409409+ machine.succeed("echo 0 > /proc/sys/vm/panic_on_oom") # allow OOMing
410410+ out = switch_to_specialisation("with-slice")
411411+ machine.fail("systemctl start testservice.service")
412412+ out = switch_to_specialisation("with-slice-non-crashing")
413413+ machine.succeed("systemctl start testservice.service")
414414+ machine.succeed("echo 1 > /proc/sys/vm/panic_on_oom") # disallow OOMing
415415+37416 '';
38417})
···11-diff --git a/tool/jt.rb b/tool/jt.rb
22-index 870d88edcb..0a6e4c367b 100755
33---- a/tool/jt.rb
44-+++ b/tool/jt.rb
55-@@ -152,13 +152,16 @@ module Utilities
66- end
77-88- def find_mx
99-- if which('mx')
1010-- 'mx'
1111-+ if ENV.key?("MX_GIT_CACHE_DIR")
1212-+ "mx-internal"
1313- else
1414-- mx_repo = find_or_clone_repo("https://github.com/graalvm/mx.git")
1515-- "#{mx_repo}/mx"
1616-+ if which('mx')
1717-+ 'mx'
1818-+ else
1919-+ mx_repo = find_or_clone_repo("https://github.com/graalvm/mx.git")
2020-+ "#{mx_repo}/mx"
2121-+ end
2222- end
2323-- end
2424-2525- def find_launcher(use_native)
2626- if use_native
2727-@@ -444,8 +447,8 @@ module Commands
2828- --no-sforceimports do not run sforceimports before building
2929- parser build the parser
3030- options build the options
3131-- graalvm build a minimal JVM-only GraalVM containing only TruffleRuby,
3232-- available by default in mxbuild/truffleruby-jvm,
3333-+ graalvm build a minimal JVM-only GraalVM containing only TruffleRuby,
3434-+ available by default in mxbuild/truffleruby-jvm,
3535- the Ruby is symlinked into rbenv or chruby if available
3636- --graal include the GraalVM Compiler in the build
3737- --native build native ruby image as well, available in mxbuild/truffleruby-native
3838-@@ -491,7 +494,7 @@ module Commands
3939- jt test compiler run compiler tests
4040- jt test integration [TESTS] run integration tests
4141- jt test bundle [--jdebug] tests using bundler
4242-- jt test gems [TESTS] tests using gems
4343-+ jt test gems [TESTS] tests using gems
4444- jt test ecosystem [TESTS] tests using the wider ecosystem such as bundler, Rails, etc
4545- jt test cexts [--no-openssl] [--no-gems] [test_names...]
4646- run C extension tests (set GEM_HOME)
···11-diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/query/SizeAndSignednessVerifier.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/query/SizeAndSignednessVerifier.java
22-index 23a76357fd2..f13694b6ed7 100644
33---- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/query/SizeAndSignednessVerifier.java
44-+++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/query/SizeAndSignednessVerifier.java
55-@@ -249,15 +249,6 @@ public final class SizeAndSignednessVerifier extends NativeInfoTreeVisitor {
66- }
77-88- private void checkSignedness(boolean isUnsigned, ResolvedJavaType type, ResolvedJavaMethod method) {
99-- if (isSigned(type)) {
1010-- if (isUnsigned) {
1111-- addError("Type " + type.toJavaName(false) + " is signed, but accessed C value is unsigned", method);
1212-- }
1313-- } else if (nativeLibs.isWordBase(type)) {
1414-- /* every Word type other than Signed is assumed to be unsigned. */
1515-- if (!isUnsigned) {
1616-- addError("Type " + type.toJavaName(false) + " is unsigned, but accessed C value is signed", method);
1717-- }
1818-- }
1919-+
2020- }
2121- }
···11-# This Makefile is used by mx to bootstrap libffi build.
22-33-# `make MX_VERBOSE=y` will report all lines executed. The actual value doesn't
44-# matter as long as it's not empty.
55-66-QUIETLY$(MX_VERBOSE) = @
77-88-.PHONY: default
99-1010-default:
1111- sed -i "s|-print-multi-os-directory||g" ../$(SOURCES)/configure
1212- $(QUIETLY) echo CONFIGURE libffi
1313- $(QUIETLY) mkdir ../$(OUTPUT)
1414- $(QUIETLY) cd ../$(OUTPUT) && ../$(SOURCES)/configure $(CONFIGURE_ARGS)
1515- $(QUIETLY) echo MAKE libffi
1616- $(QUIETLY) $(MAKE) -C ../$(OUTPUT)
+7-5
pkgs/development/compilers/nim/default.nix
···7272 nimHost = parsePlatform stdenv.hostPlatform;
7373 nimTarget = parsePlatform stdenv.targetPlatform;
74747575- bootstrapCompiler = stdenv.mkDerivation rec {
7575+ bootstrapCompiler = let
7676+ revision = "561b417c65791cd8356b5f73620914ceff845d10";
7777+ in stdenv.mkDerivation {
7678 pname = "nim-bootstrap";
7777- version = "0.20.0";
7979+ version = "g${lib.substring 0 7 revision}";
78807981 src = fetchgit {
8082 # A Git checkout is much smaller than a GitHub tarball.
8181- url = "https://github.com/nim-lang/csources.git";
8282- rev = "v${version}";
8383- sha256 = "0i6vsfy1sgapx43n226q8m0pvn159sw2mhp50zm3hhb9zfijanis";
8383+ url = "https://github.com/nim-lang/csources_v1.git";
8484+ rev = revision;
8585+ sha256 = "1c2k681knrha1zmf4abhb32i2wwd3nwflzylnqryxk753swla043";
8486 };
85878688 enableParallelBuilding = true;
···11-# This file was originally generated by https://github.com/kamilchm/go2nix v1.2.1
22-{ lib, buildGoPackage, fetchgit }:
33-44-buildGoPackage rec {
55- pname = "pprof-unstable";
66- version = "2018-08-15";
77- rev = "781f11b1fcf71fae9d185e7189b5e686f575075a";
11+{ lib
22+, buildGoModule
33+, fetchFromGitHub
44+}:
8599- goPackagePath = "github.com/google/pprof";
66+buildGoModule rec {
77+ pname = "pprof";
88+ version = "unstable-2021-09-30";
1091111- src = fetchgit {
1212- inherit rev;
1313- url = "git://github.com/google/pprof";
1414- sha256 = "1nvzwcj6h4q0lsjlri3bym4axgv848w3xz57iz5p0wz9lcd5jsmf";
1010+ src = fetchFromGitHub {
1111+ owner = "google";
1212+ repo = "pprof";
1313+ rev = "7fe48b4c820be13151ae35ce5a5e3f54f1b53eef";
1414+ sha256 = "05nr3igdigs1586qplwfm17hfw0v81jy745g6vayq7cbplljfjb1";
1515 };
16161717- goDeps = ./deps.nix;
1717+ vendorSha256 = "0yl8y3m2ia3cwxhmg1km8358a0225khimv6hcvras8r2glm69h3f";
18181919 meta = with lib; {
2020 description = "A tool for visualization and analysis of profiling data";
2121 homepage = "https://github.com/google/pprof";
2222 license = licenses.asl20;
2323 longDescription = ''
2424- pprof reads a collection of profiling samples in profile.proto format and generates reports to visualize and help analyze the data. It can generate both text and graphical reports (through the use of the dot visualization package).
2424+ pprof reads a collection of profiling samples in profile.proto format and
2525+ generates reports to visualize and help analyze the data. It can generate
2626+ both text and graphical reports (through the use of the dot visualization
2727+ package).
25282626- profile.proto is a protocol buffer that describes a set of callstacks and symbolization information. A common usage is to represent a set of sampled callstacks from statistical profiling. The format is described on the proto/profile.proto file. For details on protocol buffers, see https://developers.google.com/protocol-buffers
2929+ profile.proto is a protocol buffer that describes a set of callstacks and
3030+ symbolization information. A common usage is to represent a set of sampled
3131+ callstacks from statistical profiling. The format is described on the
3232+ proto/profile.proto file. For details on protocol buffers, see
3333+ https://developers.google.com/protocol-buffers
27342828- Profiles can be read from a local file, or over http. Multiple profiles of the same type can be aggregated or compared.
3535+ Profiles can be read from a local file, or over http. Multiple profiles of
3636+ the same type can be aggregated or compared.
29373030- If the profile samples contain machine addresses, pprof can symbolize them through the use of the native binutils tools (addr2line and nm).
3838+ If the profile samples contain machine addresses, pprof can symbolize them
3939+ through the use of the native binutils tools (addr2line and nm).
31403241 This is not an official Google product.
3342 '';
···333333 google-musicmanager = throw "google-musicmanager has been removed because Google Play Music was discontinued"; # added 2021-03-07
334334 googleAuthenticator = google-authenticator; # added 2016-10-16
335335 grantlee5 = libsForQt5.grantlee; # added 2015-12-19
336336+ graalvm8 = graalvm8-ce;
337337+ graalvm11 = graalvm11-ce;
336338 gsettings_desktop_schemas = gsettings-desktop-schemas; # added 2018-02-25
337339 gtk_doc = gtk-doc; # added 2018-02-25
338340 guileCairo = guile-cairo; # added 2017-09-24
···374376 jbuilder = dune_1; # added 2018-09-09
375377 jikes = throw "jikes was deprecated on 2019-10-07: abandoned by upstream";
376378 joseki = apache-jena-fuseki; # added 2016-02-28
379379+ jvmci8 = throw "graalvm8 and its tools were deprecated in favor of graalvm8-ce"; # added 2021-10-15
377380 json_glib = json-glib; # added 2018-02-25
378381 kdecoration-viewer = throw "kdecoration-viewer has been removed from nixpkgs, as there is no upstream activity"; # 2020-06-16
379382 k9copy = throw "k9copy has been removed from nixpkgs, as there is no upstream activity"; # 2020-11-06
···569572 mpv-with-scripts = self.wrapMpv self.mpv-unwrapped { }; # added 2020-05-22
570573 multipath_tools = multipath-tools; # added 2016-01-21
571574 mupen64plus1_5 = mupen64plus; # added 2016-02-12
575575+ mx = throw "graalvm8 and its tools were deprecated in favor of graalvm8-ce"; # added 2021-10-15
572576 mxisd = throw "mxisd has been removed from nixpkgs as it has reached end of life, see https://github.com/kamax-matrix/mxisd/blob/535e0a5b96ab63cb0ddef90f6f42c5866407df95/EOL.md#end-of-life-notice . ma1sd may be a suitable alternative."; # added 2021-04-15
573577 mysqlWorkbench = mysql-workbench; # added 2017-01-19
574578 nagiosPluginsOfficial = monitoring-plugins;