Package: dpkg
Version: 1.16.1
Control: found -1 1.20.9

Recently, #996949 came to my attention.  In summary, due to a
combination of other bugs, bad .debs can be produced.  These .debs
have broken maintainer scripts - notably, broken prerms.

The submitter there writes:
| The only way to fix the installation and allow any other apt/dpkg
| installations to complete, is to delete the broken maintainer scripts
| from /var/lib/dpkg/info/ or edit them to remove the :amd64 addition.
| This is the only way to allow a fixed package to install.

I was surprised, because I thought dpkg's prerm fallback behaviour
would enable a non-broken package's prerm to be tried instead.
I asked for repro details:

12:49 <Diziet> codehelp: Can you easily give me links to the .debs ?  I would 
               like to experiment.  You're *meant* to be able to make .debs 
               which can fix this without messing in /var.

12:52 <codehelp> Diziet:
 
https://salsa.debian.org/python-team/packages/python-envparse/-/jobs/2100822/artifacts/file/debian/output/python3-envparse_0.2.0-3+salsaci_all.deb
               - check the postinst and prerm for the py3clean and
               py3compile commands. The breakage is the :amd64 part of
               the -p argument. Fixed package is -2 from
               https://packages.debian.org/source/unstable/python-envparse

And sure enough, installing -2 over -3+salsa doesn't work.

I looked at Policy to double-check my recollection:
 
https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html#details-of-unpack-phase-of-installation-or-upgrade

|  1. Notify the currently installed package:
|
|   a. If a version of the package is already “Installed”, call
|        old-prerm upgrade new-version
|
|   b. If the script runs but exits with a non-zero exit status, dpkg will 
attempt:
|       new-prerm failed-upgrade old-version
|      If this works, the upgrade continues. If this does not work, [...]

This seemed to be a bug so I UTSL.  I found

  commit 9d3ec0f5a727d439c3cbc8885bcbc78f7a34dd0b
  Author: Raphaël Hertzog <hert...@debian.org>
  Date:   Sat Jun 18 21:36:40 2011 +0200

      dpkg: do not fallback to "new-prerm failed-upgrade" for downgrades

      If "installed-prerm upgrade" fails, dpkg tries to run "new-prerm
      failed-upgrade" so that newer versions of packages can work-around
      a bug in the prerm of the installed package.

      In the case of downgrade this logic doesn't make any sense since
      the oldest version can't be aware of the bug in the newest version
      (that did not exist when the prerm of the oldest version was
      written).

      Thus we're disabling the fallback in case of a downgrade or a
      reinstallation of the same version.

and

   dpkg (1.16.1) unstable; urgency=low
   ...

     * dpkg: if "prerm upgrade" fails when downgrading, do not try to run
       "prerm failed-upgrade" with the prerm of the oldest prerm, it can't work
       around a bug of a newer prerm anyway.

I do not agree with this change.

The claim that "it can't work around" is false.  It will often be the
case that simply running a prerm without the bug is sufficient and
correct.

Empirically, this is true in this particular case.  I constructed a
stunt copy of python3-envparse_0.2.0-2_all.deb with the Version field
changed to 0.2.0-10:

(build)root@zealot:/home/ian/d# ed x/DEBIAN/control 
762
/Version
Version: 0.2.0-2
s/2$/10
Version: 0.2.0-10
w
763
q
(build)root@zealot:/home/ian/d# dpkg-deb -b x
dpkg-deb: building package 'python3-envparse' in 'x.deb'.
(build)root@zealot:/home/ian/d# dpkg -i x.deb 
(Reading database ... 23640 files and directories currently installed.)
Preparing to unpack x.deb ...
dpkg-query: package 'python3-envparse' is not installed
Use dpkg --contents (= dpkg-deb --contents) to list archive files contents.
Traceback (most recent call last):
  File "/usr/bin/py3clean", line 210, in <module>
    main()
  File "/usr/bin/py3clean", line 196, in main
    pfiles = set(dpf.from_package(options.package))
  File "/usr/share/python3/debpython/files.py", line 53, in from_package
    raise Exception("cannot get content of %s" % package_name)
Exception: cannot get content of python3-envparse:amd64
dpkg: warning: old python3-envparse package pre-removal script subprocess 
returned error exit status 1
dpkg: trying script from the new package instead ...
dpkg: ... it looks like that went OK
Unpacking python3-envparse (0.2.0-10) over (0.2.0-3+salsaci) ...
Setting up python3-envparse (0.2.0-10) ...
(build)root@zealot:/home/ian/d#


Analysis:

Downgrades are not usual.  Higher-level package managers like apt will
not do it by default.  And indeed downgrades are not fully supported
by Debian; rather they are available on a best-effort basis.

Furthermore, this version-number dependent behaviour in maintscript
processing in dpkg is (i) anomalous and (ii) confusing.  I don't think
there are other cases where dpkg behaviour so subtly depends on
whether something is thought to be an upgrade or downgrade.

It seems to me that it is better to enable the fallback in all cases.
That would have helped the users in this case.  When it's a downgrade,
things are already going wrong and the user is already knowingly
taking some risks.  Most likely, they are a developer trying out
local, experimental or untested packages, or a user who likes to live
on the bleeding edge.

Having the fallback available even for downgrades will often make it
possible to recover from a broken package simply by reinstalling the
non-broken one (as in this case).


If you disagree and think the behavioural change should be kept, then
policy ought to be changed.  And probably, a message about skipping
the fallback would be helpful - both for un-confusing someone
debugging dpkg, and for the user/developer who is afflicted by a
broken pre-rm: it would tell them what they need to do (a bodge like I
just did).

Thanks,
Ian.


-- 
Ian Jackson <ijack...@chiark.greenend.org.uk>   These opinions are my own.  

Pronouns: they/he.  If I emailed you from @fyvzl.net or @evade.org.uk,
that is a private address which bypasses my fierce spamfilter.

Reply via email to