Package: dpkg
Version: 1.19.2
Severity: serious
Control: found -1 1.18.25

Hi,

there is a problem with update-alternatives not properly deregistering
obsolete slaves:

==========
#!/bin/sh

update-alternatives --version
update-alternatives --remove-all foobar

set -x
touch /foo /foo.1
touch /bar /bar.1
update-alternatives --display foobar
update-alternatives --install /foobar foobar /foo 23 --slave /foobar.1 foobar-1 
/foo.1 --slave /barfoo barfoo /bar --slave /barfoo.1 barfoo-1 /bar.1
update-alternatives --display foobar
rm /bar /bar.1
update-alternatives --install /foobar foobar /foo 42 --slave /foobar.1 foobar-1 
/foo.1
update-alternatives --display foobar
update-alternatives --install /foobar foobar /foo 42 --slave /foobar.1 foobar-1 
/foo.1
update-alternatives --display foobar
==========

# ./foobar.sh 
Debian update-alternatives version 1.18.25.

This is free software; see the GNU General Public License version 2 or
later for copying conditions. There is NO warranty.
update-alternatives: error: no alternatives for foobar
+ touch /foo /foo.1
+ touch /bar /bar.1
+ update-alternatives --display foobar
update-alternatives: error: no alternatives for foobar
+ update-alternatives --install /foobar foobar /foo 23 --slave /foobar.1 
foobar-1 /foo.1 --slave /barfoo barfoo /bar --slave /barfoo.1 barfoo-1 /bar.1
update-alternatives: using /foo to provide /foobar (foobar) in auto mode
+ update-alternatives --display foobar
foobar - auto mode
  link best version is /foo
  link currently points to /foo
  link foobar is /foobar
  slave barfoo is /barfoo
  slave barfoo-1 is /barfoo.1
  slave foobar-1 is /foobar.1
/foo - priority 23
  slave barfoo: /bar
  slave barfoo-1: /bar.1
  slave foobar-1: /foo.1
+ rm /bar /bar.1
+ update-alternatives --install /foobar foobar /foo 42 --slave /foobar.1 
foobar-1 /foo.1
update-alternatives: warning: forcing reinstallation of alternative /foo 
because link group foobar is broken
+ update-alternatives --display foobar
foobar - auto mode
  link best version is /foo
  link currently points to /foo
  link foobar is /foobar
  slave barfoo-1 is /barfoo.1
  slave foobar-1 is /foobar.1
*** *** *** at this point there should not be any barfoo slaves left *** *** ***
/foo - priority 42
  slave foobar-1: /foo.1
+ update-alternatives --install /foobar foobar /foo 42 --slave /foobar.1 
foobar-1 /foo.1
+ update-alternatives --display foobar
foobar - auto mode
  link best version is /foo
  link currently points to /foo
  link foobar is /foobar
  slave foobar-1 is /foobar.1
/foo - priority 42
  slave foobar-1: /foo.1

# sh foobar.sh 
Debian update-alternatives version 1.17.27.

This is free software; see the GNU General Public License version 2 or
later for copying conditions. There is NO warranty.
update-alternatives: error: no alternatives for foobar
+ touch /foo /foo.1
+ touch /bar /bar.1
+ update-alternatives --display foobar
update-alternatives: error: no alternatives for foobar
+ update-alternatives --install /foobar foobar /foo 23 --slave /foobar.1 
foobar-1 /foo.1 --slave /barfoo barfoo /bar --slave /barfoo.1 barfoo-1 /bar.1
update-alternatives: using /foo to provide /foobar (foobar) in auto mode
+ update-alternatives --display foobar
foobar - auto mode
  link currently points to /foo
/foo - priority 23
  slave barfoo: /bar
  slave barfoo-1: /bar.1
  slave foobar-1: /foo.1
Current 'best' version is '/foo'.
+ rm /bar /bar.1
+ update-alternatives --install /foobar foobar /foo 42 --slave /foobar.1 
foobar-1 /foo.1
update-alternatives: warning: forcing reinstallation of alternative /foo 
because link group foobar is broken
+ update-alternatives --display foobar
foobar - auto mode
  link currently points to /foo
/foo - priority 42
  slave foobar-1: /foo.1
Current 'best' version is '/foo'.
+ update-alternatives --install /foobar foobar /foo 42 --slave /foobar.1 
foobar-1 /foo.1
+ update-alternatives --display foobar
foobar - auto mode
  link currently points to /foo
/foo - priority 42
  slave foobar-1: /foo.1
Current 'best' version is '/foo'.

So this is reproducible in stretch, too, but not in jessie.

The change of priority is not even needed.

The problem does not occur if there is only a single broken slave to be
removed.


The slaves to be removed don't even need to be broken ...

# update-alternatives --install /test test /bin 1 --slave /one one /bin --slave 
/two two /bin --slave /three three /bin
# update-alternatives --install /test test /bin 1
# update-alternatives --install /test2 test2 /bin 1 --slave /one one /bin 
--slave /two two /bin --slave /three three /bin
update-alternatives: error: alternative three can't be slave of test2: it is a 
slave of test
# update-alternatives --display test
test - auto mode
  link best version is /bin
  link currently points to /bin
  link test is /test
  slave three is /three
/bin - priority 1

This didn't work with only two slaves being removed ...


Also the "forcing reinstallation of alternative ..." message is confusing
at this situation, as there is nothing left to be "fixed" after the new
alternative got "applied", since the new alternative is supposed to fix the
currently broken bits. That message might be useful if the alternative
is set to manual or a lower priority is being installed, that would not
imply any changes to the currently selected alternative (which has broken
slave links).
Or if the currently selected alternative was about to be reinstalled with
the same parameters s.t. it should be a no-op.

The message when adding new slaves looks much more appropriate:
  "updating alternative ... because link group ... has changed slave links"


----------

And here is the text that I initially wrote for this bug, with a
real life example, before trying to reproduce it with a few commands:

The current alternative has a broken link group, because some slave
targets are gone.
The new alternative has these slaves removed and changes the priority
value.
u-a does not properly install the new alternative, because it keeps the
broken link in the registry. Instead it gives the "forcing reinstallation"
message, which is a bit confusing.
Reinstalling the alternative with the same command works fine and cleans
up the cruft entry. Works the same with and without priority change.

I noticed this problem in a piuparts upgrade test of the nvidia driver
packages in non-free. The slave alternative is supposed to be taken over
by another package (and another alternative), but suddenly u-a started
to complain that it is still owned by the old alternative.

  + update-alternatives --display nvidia
  nvidia - auto mode
    link best version is /usr/lib/nvidia/current
    link currently points to /usr/lib/nvidia/current
    link nvidia is /usr/lib/nvidia/nvidia
    slave nvidia--libGL.so.1-x86_64-linux-gnu is 
/usr/lib/x86_64-linux-gnu/nvidia/libGL.so.1
    slave nvidia--libGLX_indirect.so.0-x86_64-linux-gnu is 
/usr/lib/x86_64-linux-gnu/libGLX_indirect.so.0
    slave nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu is 
/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.0
  /usr/lib/nvidia/current - priority 384
    slave nvidia--libGL.so.1-x86_64-linux-gnu: 
/usr/lib/x86_64-linux-gnu/nvidia/current/libGL.so.1
    slave nvidia--libGLX_indirect.so.0-x86_64-linux-gnu: 
/usr/lib/x86_64-linux-gnu/nvidia/current/libGLX_indirect.so.0
    slave nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu: 
/usr/lib/x86_64-linux-gnu/nvidia/current/libGLX_nvidia.so.0

  + update-alternatives --install /usr/lib/nvidia/nvidia nvidia 
/usr/lib/nvidia/current 390 --slave 
/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.0 
nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu 
/usr/lib/x86_64-linux-gnu/nvidia/current/libGLX_nvidia.so.0
  update-alternatives: warning: forcing reinstallation of alternative 
/usr/lib/nvidia/current because link group nvidia is broken
  + update-alternatives --display nvidia
  nvidia - auto mode
    link best version is /usr/lib/nvidia/current
    link currently points to /usr/lib/nvidia/current
    link nvidia is /usr/lib/nvidia/nvidia
    slave nvidia--libGLX_indirect.so.0-x86_64-linux-gnu is 
/usr/lib/x86_64-linux-gnu/libGLX_indirect.so.0
    slave nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu is 
/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.0
  /usr/lib/nvidia/current - priority 390
    slave nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu: 
/usr/lib/x86_64-linux-gnu/nvidia/current/libGLX_nvidia.so.0

# ls -la /etc/alternatives/nvidia*
lrwxrwxrwx 1 root root 23 Dec 18 17:12 /etc/alternatives/nvidia -> 
/usr/lib/nvidia/current
lrwxrwxrwx 1 root root 59 Dec 18 17:12 
/etc/alternatives/nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu -> 
/usr/lib/x86_64-linux-gnu/nvidia/current/libGLX_nvidia.so.0

# ls -la /usr/lib/x86_64-linux-gnu/libGLX_indirect.so.0
ls: cannot access '/usr/lib/x86_64-linux-gnu/libGLX_indirect.so.0': No such 
file or directory

# update-alternatives --install /usr/lib/nvidia/nvidia nvidia 
/usr/lib/nvidia/current 391 --slave 
/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.0 
nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu 
/usr/lib/x86_64-linux-gnu/nvidia/current/libGLX_nvidia.so.0

# update-alternatives --display nvidia
nvidia - auto mode
  link best version is /usr/lib/nvidia/current
  link currently points to /usr/lib/nvidia/current
  link nvidia is /usr/lib/nvidia/nvidia
  slave nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu is 
/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.0
/usr/lib/nvidia/current - priority 391
  slave nvidia--libGLX_nvidia.so.0-x86_64-linux-gnu: 
/usr/lib/x86_64-linux-gnu/nvidia/current/libGLX_nvidia.so.0

I thought this was a recent regression, since this worked a few months
ago when I tested this upgrade path in the nvidia driver package.
But obviously it is not, perhaps there are some more
circumstances needed to have this manifest.


Andreas

Reply via email to