Change:
die "$0: container ‘$containerName’ does not existn" ; } <ins> # 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 PIDn"; return int($1); } </ins> sub isContainerRunning { my $status = `systemctl show 'container@$containerName'`; return $status =~ /ActiveState=active/; } sub terminateContainer { <ins> my $leader = getLeader; </ins> system("machinectl", "terminate", $containerName) == 0 or die "$0: failed to terminate containern"; <ins> # 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) } </ins> } sub stopContainer {

Discussion:
When run on my container, the container doesn't shut down properly. It hangs with the following processes: See how there are only , and left in the container, so I suspect it's a problem with what does, as opposed to what I do in my container.
After 90 seconds, systemd kills the container with a SIGKILL, so that way the hang is eventually resolved. This is what the log of looks like:
I further found that when I run directly myself, the container shuts down perfectly fine. But when I first it, and then send the in it a , it doesn't shut down as expected. So myst be doing something that puts systemd in a state where it no longer cares about the signal. This is the of that systemd process inside the container when it's hung (the blank space is when I sent the signal that it ignores):
Also I haven't said that yet: immediately shuts down the machine correctly. It's likely something in that's not doing the right thing. I've re-run the strace with to get more output: This seems to reveal the error: For those not familiar with : , which nixos-containers is , triggers the . But it seems like this target file does not exist in my container at the 4 locations it's trying to find it at, so probably systemd just does nothing when it can't find that file.
Ah, interesting. While the container is running, the file does exist here: Maybe in the container gets unmounted too early in the shutdown sequence, before systemd has the chance to read this file?
OK, I think I've got the reason. In it calls (which does , which runs asynchronously and immediately returns), and then we immediately delete the , , and the . Probably lives in , so we delete it here before systemd actually gets the chance to come by there. This is supported by the observation that when I put a after the line, everything works fine. So I think the solution is the same as the solution to should be: Make block until the container is actually gone. Only after that delete the container's root. For an example of how to poll for the container being down, see . Now we just have to bring that to perl
I guess this can be closed as the PR fixing this has been merged,