fix mmdebstrap hanging if apt in download step failed (closes: #1017795)

This commit is contained in:
Johannes Schauer Marin Rodrigues 2022-08-30 21:55:57 +02:00
parent df2226fb25
commit 226f86fea9
Signed by untrusted user: josch
GPG key ID: F2CBA5C78FBD83E1
3 changed files with 60 additions and 34 deletions

View file

@ -323,3 +323,5 @@ Modes: root unshare
Needs-QEMU: true Needs-QEMU: true
Test: error-if-stdout-is-tty Test: error-if-stdout-is-tty
Test: variant-custom-timeout

View file

@ -979,19 +979,24 @@ sub run_apt_download_progress {
my $flags = fcntl($wfh, F_GETFD, 0) or error "fcntl F_GETFD: $!"; my $flags = fcntl($wfh, F_GETFD, 0) or error "fcntl F_GETFD: $!";
fcntl($wfh, F_SETFD, $flags & ~FD_CLOEXEC) or error "fcntl F_SETFD: $!"; fcntl($wfh, F_SETFD, $flags & ~FD_CLOEXEC) or error "fcntl F_SETFD: $!";
my $fd = fileno $wfh; my $fd = fileno $wfh;
# run_apt_progress() can raise an exception which would leave this function
# without cleaning up the other thread we started, making mmdebstrap hang
# in case run_apt_progress() fails -- so wrap this in eval() instead
eval {
# 2022-05-02, #debian-apt on OFTC, times in UTC+2 # 2022-05-02, #debian-apt on OFTC, times in UTC+2
# 16:57 < josch> DonKult: how is -oDebug::pkgDpkgPm=1 -oDir::Log=/dev/null # 16:57 < josch> DonKult: how is -oDebug::pkgDpkgPm=1
# a "fancy no-op"? # -oDir::Log=/dev/null a "fancy no-op"?
# 11:52 < DonKult> josch: "fancy no-op" in sofar as it does nothing to the # 11:52 < DonKult> josch: "fancy no-op" in sofar as it does nothing to
# system even through its not in a special mode ala # the system even through its not in a special mode
# simulation or download-only. It does all the things it # ala simulation or download-only. It does all the
# normally does, except that it just prints the dpkg calls # things it normally does, except that it just prints
# instead of execv() them which in practice amounts means # the dpkg calls instead of execv() them which in
# it does nothing (the Dir::Log just prevents libapt from # practice amounts means it does nothing (the Dir::Log
# creating the /var/log/apt directories. As the code # just prevents libapt from creating the /var/log/apt
# creates them even if no logs will be placed there…). As # directories. As the code creates them even if no
# said, midterm an apt --print-install-packages or # logs will be placed there…). As said, midterm an apt
# something would be nice to avoid running everything. # --print-install-packages or something would be nice
# to avoid running everything.
run_apt_progress({ run_apt_progress({
ARGV => [ ARGV => [
'apt-get', 'apt-get',
@ -1012,13 +1017,21 @@ sub run_apt_download_progress {
@{ $options->{APT_ARGV} }, @{ $options->{APT_ARGV} },
], ],
}); });
};
my $err = '';
if ($@) {
$err = "apt download failed: $@";
}
# signal the child process that we are done # signal the child process that we are done
close $wfh; close $wfh;
# and then read from it what it got # and then read from it what it got
my @listofdebs = <$fh>; my @listofdebs = <$fh>;
close $fh; close $fh;
if ($? != 0) { if ($? != 0) {
error "status child failed"; $err = "status child failed";
}
if ($err) {
error $err;
} }
# remove trailing newlines # remove trailing newlines
chomp @listofdebs; chomp @listofdebs;

View file

@ -0,0 +1,11 @@
#!/bin/sh
set -eu
export LC_ALL=C.UTF-8
# mmdebstrap used to hang forever if apt in custom mode failed to resolve
# dependencies because a process died without cleaning up its children.
# https://bugs.debian.org/1017795
ret=0
{{ CMD }} --mode={{ MODE }} --variant=custom \
--include=this-package-does-not-exist {{ DIST }} /dev/null {{ MIRROR }} || ret=1
[ $ret -eq 1 ]