summary refs log tree commit diff
path: root/pkgs/tools/virtualization
diff options
context:
space:
mode:
authorNiklas Hambüchen <mail@nh2.me>2017-12-11 04:05:15 +0100
committerNiklas Hambüchen <mail@nh2.me>2017-12-29 16:26:18 +0100
commit5d83988c1e4a666086c0ba96cae7ab6cbb41c3b0 (patch)
tree99159701fb500a235b1682f184ff1b89a8fa11ca /pkgs/tools/virtualization
parent857a71cbc51017ad660316f860a6fccf1a700c67 (diff)
downloadnixpkgs-5d83988c1e4a666086c0ba96cae7ab6cbb41c3b0.tar
nixpkgs-5d83988c1e4a666086c0ba96cae7ab6cbb41c3b0.tar.gz
nixpkgs-5d83988c1e4a666086c0ba96cae7ab6cbb41c3b0.tar.bz2
nixpkgs-5d83988c1e4a666086c0ba96cae7ab6cbb41c3b0.tar.lz
nixpkgs-5d83988c1e4a666086c0ba96cae7ab6cbb41c3b0.tar.xz
nixpkgs-5d83988c1e4a666086c0ba96cae7ab6cbb41c3b0.tar.zst
nixpkgs-5d83988c1e4a666086c0ba96cae7ab6cbb41c3b0.zip
nixos-container: Fix `destroy` terminating before it's done. Fixes #32545.
This also fixes the race condition found in #32551.

And it fixes nixops's repeated destroy/deploy being broken
(https://github.com/NixOS/nixops/issues/809).
Diffstat (limited to 'pkgs/tools/virtualization')
-rwxr-xr-xpkgs/tools/virtualization/nixos-container/nixos-container.pl26
1 files changed, 18 insertions, 8 deletions
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,14 +215,31 @@ if (!-e $confFile) {
     die "$0: container ‘$containerName’ does not exist\n" ;
 }
 
+# Return the PID of the init process of the container.
+sub getLeader {
+    my $s = `machinectl show "$containerName" -p Leader`;
+    chomp $s;
+    $s =~ /^Leader=(\d+)$/ or die "unable to get container's main PID\n";
+    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 {
@@ -229,14 +247,6 @@ sub stopContainer {
         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`;
-    chomp $s;
-    $s =~ /^Leader=(\d+)$/ or die "unable to get container's main PID\n";
-    return int($1);
-}
-
 # Run a command in the container.
 sub runInContainer {
     my @args = @_;