forked from josch/mmdebstrap
fix mmdebstrap hanging if apt in download step failed (closes: #1017795)
This commit is contained in:
parent
df2226fb25
commit
226f86fea9
3 changed files with 60 additions and 34 deletions
|
@ -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
|
||||||
|
|
81
mmdebstrap
81
mmdebstrap
|
@ -979,46 +979,59 @@ 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;
|
||||||
# 2022-05-02, #debian-apt on OFTC, times in UTC+2
|
# run_apt_progress() can raise an exception which would leave this function
|
||||||
# 16:57 < josch> DonKult: how is -oDebug::pkgDpkgPm=1 -oDir::Log=/dev/null
|
# without cleaning up the other thread we started, making mmdebstrap hang
|
||||||
# a "fancy no-op"?
|
# in case run_apt_progress() fails -- so wrap this in eval() instead
|
||||||
# 11:52 < DonKult> josch: "fancy no-op" in sofar as it does nothing to the
|
eval {
|
||||||
# system even through its not in a special mode ala
|
# 2022-05-02, #debian-apt on OFTC, times in UTC+2
|
||||||
# simulation or download-only. It does all the things it
|
# 16:57 < josch> DonKult: how is -oDebug::pkgDpkgPm=1
|
||||||
# normally does, except that it just prints the dpkg calls
|
# -oDir::Log=/dev/null a "fancy no-op"?
|
||||||
# instead of execv() them which in practice amounts means
|
# 11:52 < DonKult> josch: "fancy no-op" in sofar as it does nothing to
|
||||||
# it does nothing (the Dir::Log just prevents libapt from
|
# the system even through its not in a special mode
|
||||||
# creating the /var/log/apt directories. As the code
|
# ala simulation or download-only. It does all the
|
||||||
# creates them even if no logs will be placed there…). As
|
# things it normally does, except that it just prints
|
||||||
# said, midterm an apt --print-install-packages or
|
# the dpkg calls instead of execv() them which in
|
||||||
# something would be nice to avoid running everything.
|
# practice amounts means it does nothing (the Dir::Log
|
||||||
run_apt_progress({
|
# just prevents libapt from creating the /var/log/apt
|
||||||
ARGV => [
|
# directories. As the code creates them even if no
|
||||||
'apt-get',
|
# logs will be placed there…). As said, midterm an apt
|
||||||
'--yes',
|
# --print-install-packages or something would be nice
|
||||||
'-oDebug::pkgDpkgPm=1',
|
# to avoid running everything.
|
||||||
'-oDir::Log=/dev/null',
|
run_apt_progress({
|
||||||
$options->{dryrun}
|
ARGV => [
|
||||||
? '-oAPT::Get::Simulate=true'
|
'apt-get',
|
||||||
: (
|
'--yes',
|
||||||
"-oAPT::Keep-Fds::=$fd",
|
'-oDebug::pkgDpkgPm=1',
|
||||||
"-oDPkg::Tools::options::'cat >&$fd'::InfoFD=$fd",
|
'-oDir::Log=/dev/null',
|
||||||
"-oDpkg::Pre-Install-Pkgs::=cat >&$fd",
|
$options->{dryrun}
|
||||||
# no need to lock the database if we are just downloading
|
? '-oAPT::Get::Simulate=true'
|
||||||
"-oDebug::NoLocking=1",
|
: (
|
||||||
# no need for pty magic if we write no log
|
"-oAPT::Keep-Fds::=$fd",
|
||||||
"-oDpkg::Use-Pty=0",
|
"-oDPkg::Tools::options::'cat >&$fd'::InfoFD=$fd",
|
||||||
),
|
"-oDpkg::Pre-Install-Pkgs::=cat >&$fd",
|
||||||
@{ $options->{APT_ARGV} },
|
# no need to lock the database if we are just downloading
|
||||||
],
|
"-oDebug::NoLocking=1",
|
||||||
});
|
# no need for pty magic if we write no log
|
||||||
|
"-oDpkg::Use-Pty=0",
|
||||||
|
),
|
||||||
|
@{ $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;
|
||||||
|
|
11
tests/variant-custom-timeout
Normal file
11
tests/variant-custom-timeout
Normal 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 ]
|
Loading…
Reference in a new issue