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
|
Test: skip-tar-in-mknod
|
||||||
Modes: unshare
|
Modes: unshare
|
||||||
|
|
||||||
|
Test: zombie-reaping
|
||||||
|
Modes: unshare
|
||||||
|
|
40
mmdebstrap
40
mmdebstrap
|
@ -1964,6 +1964,23 @@ sub setup {
|
||||||
|
|
||||||
my $msg = $@;
|
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);
|
$cleanup->(0);
|
||||||
if ($msg) {
|
if ($msg) {
|
||||||
error "setup failed: $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
|
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
|
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
|
argument. Otherwise, I<command> is executed under I<sh> and the chroot
|
||||||
directory can be accessed via I<$1>. Most environment variables set by
|
directory can be accessed via I<$1>. Background (daemon) processes spawned in
|
||||||
B<mmdebstrap> (like C<DEBIAN_FRONTEND>, C<LC_ALL> and C<PATH>) are preserved.
|
a hook are not guaranteed to persist beyond the hook that created them.
|
||||||
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
|
Most environment variables set by B<mmdebstrap> (like C<DEBIAN_FRONTEND>,
|
||||||
C<MMDEBSTRAP_APT_CONFIG> environment variable. All environment variables set by
|
C<LC_ALL> and C<PATH>) are preserved. Most notably, C<APT_CONFIG> is being
|
||||||
the user are preserved, except for C<TMPDIR> which is cleared. See section
|
unset. If you need the path to C<APT_CONFIG> as written by mmdebstrap it can be
|
||||||
B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
|
found in the C<MMDEBSTRAP_APT_CONFIG> environment variable. All environment
|
||||||
B<--mode>, C<MMDEBSTRAP_FORMAT> stores the format chosen by B<--format>,
|
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,
|
C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup, extract,
|
||||||
essential, customize), C<MMDEBSTRAP_ARGV0> stores the name of the binary with
|
essential, customize), C<MMDEBSTRAP_ARGV0> stores the name of the binary with
|
||||||
which B<mmdebstrap> was executed and C<MMDEBSTRAP_VERBOSITY> stores the
|
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
|
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.
|
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>
|
=item B<cleanup>
|
||||||
|
|
||||||
Performs cleanup tasks, unless B<--skip=cleanup> is used:
|
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