#133029 dh_installdebconf make cause breakage(lack of db_stop)

#133029#5
Date:
2002-02-08 23:17:31 UTC
From:
To:
# Automatically added by dh_installdebconf
if [ "$1" = purge -a -e /usr/share/debconf/confmodule ]; then
        . /usr/share/debconf/confmodule
        db_purge
fi
# End automatically added section

However, there may be a package, that provides additional features to other
daemons.  Said package may deregister itself during postrm, and restart the
other service/daemon.  Because the above block doesn't call db_stop, there is
the potential for the fd problem.

Additionally, it could be argued that there should be no communication with
debconf after db_purge is called.  However, one may still need to fetch shared
values, so that's a difficult one to deside.

I haven't actually seen a problem in the real world, but it's possible that
one could arise.

#133029#10
Date:
2002-02-09 00:43:38 UTC
From:
To:
Adam Heath wrote:

Uh huh. <bap>

#133029#17
Date:
2006-04-17 12:55:41 UTC
From:
To:
dh_installdebconf inserts code into the postrm which calls db_purge
(unprotected, but a debconf protocol dump shows that PURGE returns status
0).  It fails to call db_stop, as warned by #133029.

This leaves our postinst will all stdout output redirected into confmodule,
which seems to cause the mess.

Editing /var/lib/dpkg/info/amavisd-new.postrm first line to #!/bin/sh -x
shows that, as expected, calling confmodule in the middle of the script is
an extremely dumb thing to do, as it runs part of the script twice...

Instead of moving #DEBHELPER# to the top of the script, or trying to
second-guess what kind of mess we could get into yet again, I am disabling
debhelper-included dh_installdebconf scripts, and doing it by ourselves.

Report cc'ed to #133029 so that Joey can be reminded of that report, and
that it does cause issues on real world packages (note that I am not blaming
the bug on debhelper, it is just that our usage is not compatible with the
script it produces).

Just for the kick of it, here's the full dump, with debconf protocol debug
enabled.

(steps to reproduce):
login in a sarge chroot (pbuilder, new debootstrap one)
apt-get install amavisd-new
sed -i s/sarge/testing/g /etc/apt/sources.list
apt-get update ; apt-get install amavisd-new

(amavisd-new will be upgraded correctly)

export DEBCONF_DEBUG=developer
sed -i '1 s@#!.*@#!/bin/sh -x@' /var/lib/dpkg/info/amavisd-new.postrm
dpkg -P amavisd-new


[output of dpkg -P amavisd-new]
(Reading database ... 12164 files and directories currently installed.)
Removing amavisd-new ...
+ set -e
+ '[' remove = purge ']'
+ '[' remove = purge ']'
+ exit 0
Purging configuration files for amavisd-new ...
+ set -e
+ dpkg-statoverride --remove /var/lib/amavis
+ dpkg-statoverride --remove /var/lib/amavis/db
+ dpkg-statoverride --remove /var/lib/amavis/tmp
+ dpkg-statoverride --remove /var/lib/amavis/virusmails
+ dpkg-statoverride --remove /var/run/amavis
+ getent passwd amavis
+ deluser amavis
Removing user `amavis'...
done.
+ getent group amavis
+ echo 'Removing amavis files and directories...'
Removing amavis files and directories...
+ '[' -d /var/lib/amavis ']'
+ rm -fr /var/lib/amavis
+ '[' -d /etc/amavis ']'
+ rm -fr /etc/amavis
+ '[' purge = purge ']'
+ '[' -e /usr/share/debconf/confmodule ']'
+ . /usr/share/debconf/confmodule
++ '[' '!' '' ']'
++ PERL_DL_NONLAZY=1
++ export PERL_DL_NONLAZY
++ exec /usr/share/debconf/frontend /var/lib/dpkg/info/amavisd-new.postrm
purge
debconf (developer): frontend started
debconf (developer): frontend running, package name is amavisd-new
debconf (developer): starting /var/lib/dpkg/info/amavisd-new.postrm purge
+ set -e
+ dpkg-statoverride --remove /var/lib/amavis
No override present.
+ true
+ dpkg-statoverride --remove /var/lib/amavis/db
No override present.
+ true
+ dpkg-statoverride --remove /var/lib/amavis/tmp
No override present.
+ true
+ dpkg-statoverride --remove /var/lib/amavis/virusmails
No override present.
+ true
+ dpkg-statoverride --remove /var/run/amavis
No override present.
+ true
+ getent passwd amavis
+ getent group amavis
+ echo 'Removing amavis files and directories...'
debconf (developer): <-- Removing amavis files and directories...
+ '[' -d /var/lib/amavis ']'
+ '[' -d /etc/amavis ']'
+ '[' purge = purge ']'
+ '[' -e /usr/share/debconf/confmodule ']'
+ . /usr/share/debconf/confmodule
++ '[' '!' 1 ']'
++ '[' -z '' ']'
++ exec
++ DEBCONF_REDIR=1
++ export DEBCONF_REDIR
+ db_purge
+ _db_cmd 'PURGE '
+ echo 'PURGE '
debconf (developer): <-- PURGE
+ local 'IFS=
'
+ local _LINE
+ read -r _LINE
+ RET=20 Unsupported command "removing" (full line was "Removing amavis
files an
d directories...") received from confmodule.
+ return 20
debconf (developer): --> 0
dpkg: error processing amavisd-new (--purge):
 subprocess post-removal script returned error exit status 128
Errors were encountered while processing:
 amavisd-new

#133029#22
Date:
2006-04-20 00:14:10 UTC
From:
To:
    Henrique> This leaves our postinst will all stdout output
    Henrique> redirected into confmodule, which seems to cause the
    Henrique> mess.

I don't particularly like the debconf standard of using stdout for its
command stream. Too many programs use stdout to write anything they
desire. Not only that, but the error generated is very obscure (unless
you have debugging turned on and are competent enough to understand
it). I don't think it was even obvious that the error was being
generated from debconf. It would be better to redirect stdout -->
/dev/null IMHO, and use some other hard coded file handle for debconf.

In this case it would appear that the problem is caused by echo
statements in our script (do we really need them?). Like the
following:

    Henrique> + echo 'Removing amavis files and directories...'
    Henrique> Removing amavis files and directories...

However all you need is for one of the many utility programs we use,
eg:

    Henrique> + deluser amavis
    Henrique> Removing user `amavis'...
    Henrique> done.

to output the status information to stdout instead of stderr (I assume
it is currently using stderr as this line didn't seem to upset
debconf) for some obscure/untested condition, and our scripts starts
outputting to stdout again. In fact, I would argue that deluser should
be outputting this to stdout, the status information shown above is
hardly an error condition.

#133029#27
Date:
2006-04-20 00:18:44 UTC
From:
To:
I don't disagree, but you can fix it pretty easily by doing

  exec 1>&2;

right?

Justin

#133029#32
Date:
2006-04-20 00:23:47 UTC
From:
To:
    Justin> I don't disagree, but you can fix it pretty easily by doing

    Justin> exec 1>&2;

    Justin> right?

Won't this break debconf commands?

#133029#37
Date:
2006-04-20 00:27:36 UTC
From:
To:
Meh, I don't know, what I mean is, you can use exec to avoid lots of
echo >&3 foo if you have a large chunk of not-debconf stuff.

#133029#42
Date:
2013-08-17 22:59:07 UTC
From:
To:
Hello,

Adam Heath, 2002-02-08 17:17-0600:

This is just an update to point out that it has been seen in the real
world, as I just ran into that issue while packaging pluxml (#630467).

pluxml is a blog engine, so upcoming my package installs some
configuration for apache2 or lighttpd and then reloads these daemons. No
problem in postinst, where at the end of the script:
1. I call db_stop;
2. dh_installdebconf adds nothing;
3 the script exists fine.

But in postrm, things happen differently. I remove the configuration
from apache2 or lighttpd, reload these daemons, and at the end of the
script:
1. I call db_stop;
2. dh_installdebconf inserts some code that sources
    /usr/share/debconf/confmodule again, which starts debconf (I do not
    know the dirty details) and calls db_purge;
3. the script stalls, or rather, exists, but stays defunct with a
    debconf wrapper waiting for nothing, as it seems.

I solved that problem by moving my call to db_stop after the #DEBHELPER#
placeholder.

Would there be a problem in adding a call to db_stop after db_purge, in
the code added to postrm by dh_installdebconf? Otherwise, that problem
could be mitigated by adding a notice in dh_installdebconf(1) and
probably in debconf-devel(7) too, telling people to put their call to
db_stop after the debhelper placeholder, as I did.

Librement,