diff --git a/coverage.txt b/coverage.txt index f71e14a..9e10836 100644 --- a/coverage.txt +++ b/coverage.txt @@ -430,3 +430,6 @@ Modes: root unshare Test: skip-tar-in-mknod Modes: unshare + +Test: zombie-reaping +Modes: unshare diff --git a/mmdebstrap b/mmdebstrap index aeebebb..f422438 100755 --- a/mmdebstrap +++ b/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 is an existing executable file from C<$PATH> or if I does not contain any shell metacharacters, then I is directly exec-ed with the path to the chroot directory passed as the first argument. Otherwise, I is executed under I and the chroot -directory can be accessed via I<$1>. Most environment variables set by -B (like C, C and C) are preserved. -Most notably, C is being unset. If you need the path to -C as written by mmdebstrap it can be found in the -C environment variable. All environment variables set by -the user are preserved, except for C which is cleared. See section -B. Furthermore, C will store the mode set by -B<--mode>, C 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 (like C, +C and C) are preserved. Most notably, C is being +unset. If you need the path to C as written by mmdebstrap it can be +found in the C environment variable. All environment +variables set by the user are preserved, except for C which is cleared. +See section B. Furthermore, C will store the mode set +by B<--mode>, C stores the format chosen by B<--format>, C stores which hook is currently run (setup, extract, essential, customize), C stores the name of the binary with which B was executed and C stores the @@ -7480,6 +7499,11 @@ This step is not carried out in B mode. Unmount everything that was mounted during the B stage and restores F and F if necessary. +=item B + +Wait for (reap) still running processes (background processes or zombie +processes), unless B<--skip=zombie-reaping> is used. + =item B Performs cleanup tasks, unless B<--skip=cleanup> is used: diff --git a/tests/zombie-reaping b/tests/zombie-reaping new file mode 100644 index 0000000..83c9c1b --- /dev/null +++ b/tests/zombie-reaping @@ -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