diff --git a/pkgs/tools/virtualization/nixos-container/nixos-container.pl b/pkgs/tools/virtualization/nixos-container/nixos-container.pl index fefdcd614a5..2cb723a7b71 100755 --- a/pkgs/tools/virtualization/nixos-container/nixos-container.pl +++ b/pkgs/tools/virtualization/nixos-container/nixos-container.pl @@ -7,6 +7,7 @@ use File::Slurp; use Fcntl ':flock'; use Getopt::Long qw(:config gnu_getopt); use Cwd 'abs_path'; +use Time::HiRes; my $nsenter = "@utillinux@/bin/nsenter"; my $su = "@su@"; @@ -214,21 +215,6 @@ if (!-e $confFile) { die "$0: container ‘$containerName’ does not exist\n" ; } -sub isContainerRunning { - my $status = `systemctl show 'container\@$containerName'`; - return $status =~ /ActiveState=active/; -} - -sub terminateContainer { - system("machinectl", "terminate", $containerName) == 0 - or die "$0: failed to terminate container\n"; -} - -sub stopContainer { - system("systemctl", "stop", "container\@$containerName") == 0 - or die "$0: failed to stop container\n"; -} - # Return the PID of the init process of the container. sub getLeader { my $s = `machinectl show "$containerName" -p Leader`; @@ -237,6 +223,30 @@ sub getLeader { return int($1); } +sub isContainerRunning { + my $status = `systemctl show 'container\@$containerName'`; + return $status =~ /ActiveState=active/; +} + +sub terminateContainer { + my $leader = getLeader; + system("machinectl", "terminate", $containerName) == 0 + or die "$0: failed to terminate container\n"; + # Wait for the leader process to exit + # TODO: As for any use of PIDs for process control where the process is + # not a direct child of ours, this can go wrong when the pid gets + # recycled after a PID overflow. + # Relying entirely on some form of UUID provided by machinectl + # instead of PIDs would remove this risk. + # See https://github.com/NixOS/nixpkgs/pull/32992#discussion_r158586048 + while ( kill 0, $leader ) { Time::HiRes::sleep(0.1) } +} + +sub stopContainer { + system("systemctl", "stop", "container\@$containerName") == 0 + or die "$0: failed to stop container\n"; +} + # Run a command in the container. sub runInContainer { my @args = @_;