[Bug 1941716] Re: Apt hook of needrestart hang with DEBIAN_FRONTEND=noninteractive
Christian Ehrhardt
1941716 at bugs.launchpad.net
Mon Sep 13 08:42:30 UTC 2021
Thanks for the checks Robie, thereby only to consider improving Hirsute
then I guess?
** Also affects: needrestart (Ubuntu Hirsute)
Importance: Undecided
Status: New
** Changed in: needrestart (Ubuntu)
Status: Triaged => Fix Released
** Changed in: needrestart (Ubuntu Hirsute)
Status: New => Triaged
** Changed in: needrestart (Ubuntu Hirsute)
Importance: Undecided => High
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to needrestart in Ubuntu.
https://bugs.launchpad.net/bugs/1941716
Title:
Apt hook of needrestart hang with DEBIAN_FRONTEND=noninteractive
Status in needrestart package in Ubuntu:
Fix Released
Status in needrestart source package in Hirsute:
Triaged
Bug description:
I had some of my test runs blocked and eventually found this was due
to a kernel upgrade without reboot making needrestart to block
ignoring DEBIAN_FRONTEND=noninteractive in the apt post invoke for
needrestart.
Repro:
1. Start in a Focal VM
2. sudo vim /etc/apt/sources.list
# bump it to hirsute
Situation Now:
$ uname -a
Linux f-testupgradeissue-needrestart 5.4.0-59-generic #65-Ubuntu SMP Thu Dec 10 12:01:51 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ ll /boot/vmlinuz*
lrwxrwxrwx 1 root root 25 Aug 25 14:02 /boot/vmlinuz -> vmlinuz-5.11.0-31-generic
-rw------- 1 root root 14742976 Aug 11 11:32 /boot/vmlinuz-5.11.0-31-generic
-rw------- 1 root root 11686656 Dec 10 2020 /boot/vmlinuz-5.4.0-59-generic
lrwxrwxrwx 1 root root 24 Jan 5 2021 /boot/vmlinuz.old -> vmlinuz-5.4.0-59-generic
(any other means of a mismatch in running / on-disk kernel will do as
well)
3. Without reboot needrestart will rightfully complain like
```
$ needrestart -k
Scanning linux images...
Pending kernel upgrade!
Running kernel version:
5.4.0-59-generic
Diagnostics:
The currently running kernel version is not the expected kernel version 5.11.0-31-generic.
Restarting the system to load the new kernel will not be handled automatically, so you should consider rebooting. [Return]
```
That is fine if called interactively.
The same check is also done in the hook that is in apt so apt actions will
trigger this as well:
In a shell with apt, needrestart will eventually detect that and use ncurses
style popup (fine).
The problem comes with non-intractive modes.
This is meant to be used by scripts and any such to NOT be locked in
an interactive prompt while running automation.
But the following combinations still run into interactive prompts:
a) export DEBIAN_FRONTEND=noninteractive; sudo apt install --reinstall hello
=> blocks in the ncurses popup
b) removing the terminal if running the same via a script blocks in the
console output
```
ubuntu at f-testupgradeissue-needrestart:~$ cat ./test.sh
#!/bin/bash
export DEBIAN_FRONTEND=noninteractive
apt-get -q --assume-yes --allow-unauthenticated -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install --reinstall hello
echo done
ubuntu at f-testupgradeissue-needrestart:~$ sudo ./test.sh
Reading package lists...
Building dependency tree...
Reading state information...
The following packages were automatically installed and are no longer required:
at bsdmainutils dconf-gsettings-backend dconf-service gcc-10-base glib-networking glib-networking-common glib-networking-services gsettings-desktop-schemas libdconf1 libdns-export1109
libffi7 libfl2 libhogweed5 libicu66 libjson-c4 libmpdec2 libnettle7 libperl5.30 libproxy1v5 libpython3.8 libpython3.8-minimal libpython3.8-stdlib libreadline5 libsoup2.4-1 ncal
perl-modules-5.30 popularity-contest python3-entrypoints python3-requests-unixsocket python3.8 python3.8-minimal
Use 'sudo apt autoremove' to remove them.
0 upgraded, 0 newly installed, 1 reinstalled, 0 to remove and 0 not upgraded.
Need to get 0 B/28.2 kB of archives.
After this operation, 0 B of additional disk space will be used.
(Reading database ... 100504 files and directories currently installed.)
Preparing to unpack .../hello_2.10-2ubuntu2_amd64.deb ...
Unpacking hello (2.10-2ubuntu2) over (2.10-2ubuntu2) ...
Setting up hello (2.10-2ubuntu2) ...
Processing triggers for man-db (2.9.4-2) ...
Processing triggers for install-info (6.7.0.dfsg.2-6) ...
Scanning processes...
Scanning candidates...
Scanning linux images...
Pending kernel upgrade!
Running kernel version:
5.4.0-59-generic
Diagnostics:
The currently running kernel version is not the expected kernel version 5.11.0-31-generic.
Restarting the system to load the new kernel will not be handled automatically, so you should consider rebooting. [Return]
```
IMHO the noninteractive should really stay non-interactive or at least have
a timeout. I had a few automations of mine blocked by this infinitely.
We have
$ cat /etc/apt/apt.conf.d/99needrestart
...
DPkg::Post-Invoke {"test -x /usr/lib/needrestart/apt-pinvoke && /usr/lib/needrestart/apt-pinvoke || true"; };
$ cat /usr/lib/needrestart/apt-pinvoke
...
exec /usr/sbin/needrestart "$@"
This in our case comes down to match:
$ sudo DEBIAN_FRONTEND=noninteractive /usr/sbin/needrestart
And indeed that behaves the same as needrestart does:
$is_tty = 0 if($opt_r eq 'i' && exists($ENV{DEBIAN_FRONTEND}) && $ENV{DEBIAN_FRONTEND} eq 'noninteractive');
$opt_r = 'l' if(!$is_tty && $opt_r eq 'i');
If we explicitly set "listing" mode it is really non-interactive.
$ sudo DEBIAN_FRONTEND=noninteractive /usr/sbin/needrestart -r l
^^ works fine
So what do these lines in the code above actually mean.
The second one is "downgrade to l if there is no tty)
The first one means
If "i" is requested
AND noninteractive
Then set is_tty=0
You'd think that makes it run like "-r l" in DEBIAN_FRONTEND=noninteractive
but it does not.
Debugging-wise is seems to work, pre/mod/post these lines I got:
I: is_tty = 1 opt_r = i DEBIAN_FRONTEND = noninteractive
II: is_tty = 0 opt_r = i DEBIAN_FRONTEND = noninteractive
III: is_tty = 0 opt_r = l DEBIAN_FRONTEND = noninteractive
So it does reset is_tty and it does set opt_r to l, but eventually it
still blocks :-/
This happens in
```
sub _announce {
my $self = shift;
my $message = shift;
my %vars = @_;
print "\n";
$self->wprint(\*STDOUT, '', '', __x("Pending kernel upgrade!\n\nRunning kernel version:\n {kversion}\n\nDiagnostics:\n {message}\n\nRestarting the system to load the new kernel will not be handled automatically, so you should consider rebooting. [Return]\n",
kversion => $vars{KVERSION},
message => $message,
));
<STDIN> if (-t *STDIN && -t *STDOUT);
}
```
Of file:
/usr/share/perl5/NeedRestart/UI/stdio.pm
We see that this is a problem because it only checks if it has an STDIN, but not
if it is meant to run non-interactively.
I'd suggest to prepend with an argument that can force-disable the
interactive wait.
From looking at the code the same seems to apply to announce_ehint and
announce_ucode.
And indeed running it in easy mode stops it twice,
once for the kernel report that I already reported and once
for the same code in annunce_ehint for the easy mode.
So I guess all those announces should be stopped from being interactive.
Adding arguments and logic might make this change rather messy.
I wondered if the following could be enough:
The following is a way smaller fix, but it pushes debian awareness deeper into
the code. At least it seems to work fine for my testing,
but I'm interested in a second pair of eyes on this:
--- /usr/share/perl5/NeedRestart/UI/stdio.pm.orig 2021-08-26 08:39:15.601085356 +0000
+++ /usr/share/perl5/NeedRestart/UI/stdio.pm 2021-08-26 08:43:05.257583706 +0000
@@ -43,7 +43,7 @@
kversion => $vars{KVERSION},
message => $message,
));
- <STDIN> if (-t *STDIN && -t *STDOUT);
+ <STDIN> if (-t *STDIN && -t *STDOUT && !(exists($ENV{DEBIAN_FRONTEND}) && $ENV{DEBIAN_FRONTEND} eq 'noninteractive'));
}
@@ -77,7 +77,7 @@
EHINT
- <STDIN> if (-t *STDIN && -t *STDOUT);
+ <STDIN> if (-t *STDIN && -t *STDOUT && !(exists($ENV{DEBIAN_FRONTEND}) && $ENV{DEBIAN_FRONTEND} eq 'noninteractive'));
}
@@ -90,7 +90,7 @@
current => $vars{CURRENT},
avail => $vars{AVAIL},
));
- <STDIN> if (-t *STDIN && -t *STDOUT);
+ <STDIN> if (-t *STDIN && -t *STDOUT && !(exists($ENV{DEBIAN_FRONTEND}) && $ENV{DEBIAN_FRONTEND} eq 'noninteractive'));
}
@@ -141,7 +141,7 @@
return $s;
}
- $i = <STDIN> if(-t *STDIN && -t *STDOUT);
+ $i = <STDIN> if (-t *STDIN && -t *STDOUT && !(exists($ENV{DEBIAN_FRONTEND}) && $ENV{DEBIAN_FRONTEND} eq 'noninteractive'));
unless(defined($i)) {
$i = 'n';
last;
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/needrestart/+bug/1941716/+subscriptions
More information about the foundations-bugs
mailing list