Wait for (reap) potential zombies and otherwise long-running background processes
Otherwise they might hog resources like /dev/null which can then not be unmounted resulting in their mountpoints (the regular files) not being removable and then the removal of device nodes in run_cleanup (if mmdebstrap is run with --skip=output/dev) will fail. Another potential solution would be to run each hook and apt invocation in its own process namespace but this would require to remount /proc and this in turn would require a new mount namespace as well but we'd like to keep the mount namespace across multiple hooks...
This commit is contained in:
parent
98b3c7f2cd
commit
d0568a2b9e
3 changed files with 74 additions and 8 deletions
|
@ -430,3 +430,6 @@ Modes: root unshare
|
|||
|
||||
Test: skip-tar-in-mknod
|
||||
Modes: unshare
|
||||
|
||||
Test: zombie-reaping
|
||||
Modes: unshare
|
||||
|
|
40
mmdebstrap
40
mmdebstrap
|
@ -1964,6 +1964,23 @@ sub setup {
|
|||
|
||||
my $msg = $@;
|
||||
|
||||
# Wait for (reap) potential zombies and otherwise long-running background
|
||||
# processes or otherwise they might hog resources like /dev/null which can
|
||||
# then not be unmounted resulting in their mountpoints (the regular files)
|
||||
# not being removable and then the removal of device nodes in run_cleanup
|
||||
# (if mmdebstrap is run with --skip=output/dev) will fail.
|
||||
if (any { $_ eq 'zombie-reaping' } @{ $options->{skip} }) {
|
||||
info "skipping zombie-reaping as requested";
|
||||
} else {
|
||||
if (waitpid(-1, POSIX::WNOHANG) >= 0) {
|
||||
info "waiting for background processes to finish...";
|
||||
}
|
||||
while ((my $child = waitpid(-1, 0)) > 0) {
|
||||
my $status = $? >> 8;
|
||||
info "PID $child exited with exit code $status";
|
||||
}
|
||||
}
|
||||
|
||||
$cleanup->(0);
|
||||
if ($msg) {
|
||||
error "setup failed: $msg";
|
||||
|
@ -7238,14 +7255,16 @@ hook. Otherwise, if I<command> is an existing executable file from C<$PATH> or
|
|||
if I<command> does not contain any shell metacharacters, then I<command> is
|
||||
directly exec-ed with the path to the chroot directory passed as the first
|
||||
argument. Otherwise, I<command> is executed under I<sh> and the chroot
|
||||
directory can be accessed via I<$1>. Most environment variables set by
|
||||
B<mmdebstrap> (like C<DEBIAN_FRONTEND>, C<LC_ALL> and C<PATH>) are preserved.
|
||||
Most notably, C<APT_CONFIG> is being unset. If you need the path to
|
||||
C<APT_CONFIG> as written by mmdebstrap it can be found in the
|
||||
C<MMDEBSTRAP_APT_CONFIG> environment variable. All environment variables set by
|
||||
the user are preserved, except for C<TMPDIR> which is cleared. See section
|
||||
B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
|
||||
B<--mode>, C<MMDEBSTRAP_FORMAT> stores the format chosen by B<--format>,
|
||||
directory can be accessed via I<$1>. Background (daemon) processes spawned in
|
||||
a hook are not guaranteed to persist beyond the hook that created them.
|
||||
|
||||
Most environment variables set by B<mmdebstrap> (like C<DEBIAN_FRONTEND>,
|
||||
C<LC_ALL> and C<PATH>) are preserved. Most notably, C<APT_CONFIG> is being
|
||||
unset. If you need the path to C<APT_CONFIG> as written by mmdebstrap it can be
|
||||
found in the C<MMDEBSTRAP_APT_CONFIG> environment variable. All environment
|
||||
variables set by the user are preserved, except for C<TMPDIR> which is cleared.
|
||||
See section B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set
|
||||
by B<--mode>, C<MMDEBSTRAP_FORMAT> stores the format chosen by B<--format>,
|
||||
C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup, extract,
|
||||
essential, customize), C<MMDEBSTRAP_ARGV0> stores the name of the binary with
|
||||
which B<mmdebstrap> was executed and C<MMDEBSTRAP_VERBOSITY> stores the
|
||||
|
@ -7480,6 +7499,11 @@ This step is not carried out in B<extract> mode.
|
|||
Unmount everything that was mounted during the B<mount> stage and restores
|
||||
F</usr/sbin/policy-rc.d> and F</usr/sbin/start-stop-daemon> if necessary.
|
||||
|
||||
=item B<zombie-reaping>
|
||||
|
||||
Wait for (reap) still running processes (background processes or zombie
|
||||
processes), unless B<--skip=zombie-reaping> is used.
|
||||
|
||||
=item B<cleanup>
|
||||
|
||||
Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
||||
|
|
39
tests/zombie-reaping
Normal file
39
tests/zombie-reaping
Normal file
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
set -eu
|
||||
export LC_ALL=C.UTF-8
|
||||
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
||||
|
||||
[ {{ MODE }} = "unshare" ]
|
||||
|
||||
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
|
||||
|
||||
prefix=
|
||||
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
|
||||
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
|
||||
if [ ! -e /mmdebstrap-testenv ]; then
|
||||
echo "this test modifies the system and should only be run inside a container" >&2
|
||||
exit 1
|
||||
fi
|
||||
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
|
||||
fi
|
||||
prefix="runuser -u ${SUDO_USER:-user} --"
|
||||
fi
|
||||
|
||||
MMTARFILTER=
|
||||
[ -x /usr/bin/mmtarfilter ] && MMTARFILTER=/usr/bin/mmtarfilter
|
||||
[ -x ./tarfilter ] && MMTARFILTER=./tarfilter
|
||||
|
||||
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt \
|
||||
--skip=output/dev \
|
||||
--customize-hook='chroot "$1" sh -c "sleep 1m > /dev/null" &' \
|
||||
{{ DIST }} - {{ MIRROR }} \
|
||||
| "$MMTARFILTER" --path-exclude="/dev" \
|
||||
> /tmp/debian-chroot.tar
|
||||
|
||||
origfilter() {
|
||||
< ./cache/mmdebstrap-{{ DIST }}-apt.tar \
|
||||
"$MMTARFILTER" --path-exclude="/dev/*" --path-exclude="/dev"
|
||||
}
|
||||
|
||||
origfilter | cmp - /tmp/debian-chroot.tar \
|
||||
|| origfilter | diffoscope - /tmp/debian-chroot.tar
|
Loading…
Reference in a new issue