Re: Bug#504880: Disambiguate "installed" for packages
Steve Langasek <firstname.lastname@example.org> writes:
> On Wed, Jul 21, 2010 at 01:52:50PM -0700, Russ Allbery wrote:
>> + Sometimes, a package requires another package to be unpacked
>> + <em>and</em> configured before it can be unpacked. In this
>> + case, the dependent package must specify this dependency in
>> + the <tt>Pre-Depends</tt> control field.
> I think "depending package" is clearer than "dependent package", since
> there's less possibility of confusion with "dependency". (The usage
> "dependent package" does not currently exist elsewhere in Policy.)
>> + The package will not yet be unpacked, so
>> + the <prgn>preinst</prgn> script cannot rely on any files
>> + included in its package. Only essential packages and
>> + pre-dependencies (<tt>Pre-Depends</tt>) may be assumed to be
>> + available. Pre-dependencies will be at least unpacked.
>> + They may be only unpacked or "Half-Configured", not
>> + completely configured, but only if a previous version of the
>> + pre-dependency was completely configured and the
>> + pre-dependency had not been removed since then.
> Maybe it would be clearer to write it this way?
> Pre-dependencies will have been configured at least once, but at the
> time the preinst is called they may only be in an unpacked or
> "Half-Configured" state if a previous version of the pre-dependency
> was completely configured and has not been removed (uninstalled?)
> since then.
Yeah, that looks good to me. Changed.
> Does dpkg provide any guarantee that the dependencies of the
> pre-dependency are also present at this point? If it doesn't, I think
> that should be considered a bug in dpkg, since you may be invoking a
> command that links against a library whose soname has changed since the
> last time the pre-dep package was configured. If it /does/ provide this
> guarantee, I think it should be documented in Policy.
I believe they can be in the same state as the pre-dependency itself for
exactly the same reasons, no? Upgrades don't require deconfiguring
packages that depend on the package being upgraded, so if you abort in the
middle of upgrading a package the pre-dependency depends on, the
pre-dependency is still present and configured on the system, so dpkg will
treat the pre-dependency as satisfied.
I've not changed any wording in this area for this bug.
>> + The files contained in the package will be unpacked. All
>> + package dependencies will at least be unpacked. If there
>> + are no circular dependencies involved, all package
>> + dependencies will be configured.
> Should this include a pointer to the section documenting the rules for
> breaking circular dependencies?
Added a reference.
>> + unpacked in some error situations.<footnote>
>> + For example, suppose packages foo and bar are installed
>> + with foo depending on bar. If an upgrade of bar were
>> + started and then aborted, and then an attempt to remove
>> + foo failed because its <prgn>prerm</prgn> script failed,
>> + foo's <tt>postinst abort-remove</tt> would be called with
>> + bar only "Half-Installed".
>> + </footnote>
>> - </list>
>> + </taglist>
>> + </p>
> This footnote is interesting to me because although it accurately
> documents dpkg's behavior, I'm not sure what implications it has for how
> packages should guard against this case. I think I've always ignored
> this possibility in my maintainer scripts, and will continue to do so on
> the grounds that any attempt to handle this gracefully is likely to
> introduce much greater complexity (and therefore bugs) with very little
> upside (when all is said and done, a package you were trying to remove
> is still installed, so do we care if it configures successfully?)
> If we can make a straightforward recommendation to maintainers for how
> to handle this case, I think we should include that in the footnote.
> Otherwise, if it shouldn't affect how we write maintainer scripts,
> perhaps it's better not to have this footnote at all since it would only
> lead to maintainers trying to be too clever and shooting themselves in
> the foot?
I think we should put it in the main text. I've now added, after the
footnote and in the main text:
The <prgn>postinst</prgn> should still attempt any actions
for which its dependencies are required, since they will
normally be available, but consider the correct error
handling approach if those actions fail. Aborting
the <prgn>postinst</prgn> action if commands or facilities
from the package dependencies are not available is often the
which I think is roughly what you're doing and what most people are doing
and which I think is the generally best approach.
>> + The <prgn>postrm</prgn> script is called after the package's
>> + files have been removed or replaced. The package
>> + whose <prgn>postrm</prgn> is being called may have
>> + previously been deconfigured and only be unpacked, at which
>> + point subsequent package changes do not consider its
>> + dependencies. Therefore, all <prgn>postrm</prgn> actions
>> + may only rely on essential packages and cannot assume that
>> + the package's dependencies are available.
> True as written, but less helpful than it should be. There are a number
> of cases where postrm scripts still need to *try* to invoke
> non-essential functionality, and fail gracefully if it's unavailable;
> this should be explicitly encouraged so that maintainers don't come away
> thinking they shouldn't try to clean up after themselves.
> Ex.: if you have a package that manages a config file with ucf, you
> *must* call ucf --purge from "postrm purge" if ucf is present on the
> system at this point; failure to do so will give completely unintuitive
> handling of the config file on package purge && reinstall.
> Proposed wording (improvements requested):
> Therefore, all <prgn>postrm</prgn> actions may only rely on essential
> packages and must gracefully omit anything requiring the package's
> dependencies when those dependencies are unavailable.
I now have, as the end of this paragraph:
Therefore, all <prgn>postrm</prgn> actions
may only rely on essential packages and must gracefully skip
any actions that require the package's dependencies if those
dependencies are unavailable.<footnote>
This is often done by checking whether the command or
facility the <prgn>postrm</prgn> intends to call is
available before calling it. For example:
if [ "$1" = purge ] && [ -e /usr/share/debconf/confmodule ]; then
in <prgn>postrm</prgn> purges the <prgn>debconf</prgn>
configuration for the package
if <package>debconf</package> is installed.
> --> Packages involved in circular dependencies may not be able to rely on
> their dependencies being configured before they themselves are
> configured, depending on which side of the break of the circular
> dependency loop they happen to be on.
>> The <tt>Depends</tt> field should also be used if the
>> - <prgn>postinst</prgn>, <prgn>prerm</prgn> or
>> - <prgn>postrm</prgn> scripts require the package to be
>> - present in order to run. Note, however, that the
>> - <prgn>postrm</prgn> cannot rely on any non-essential
>> - packages to be present during the <tt>purge</tt>
>> - phase.
>> + <prgn>postinst</prgn> or <prgn>prerm</prgn> scripts
>> + require the depended-on package to be unpacked or
>> + configured in order to run. In the case of <tt>postinst
>> + configure</tt>, the depended-on packages will be unpacked
>> + and configured first. (If both packages are involved in a
>> + dependency loop, this might not work as expected; see the
>> + explanation a few paragraphs back.) In the case
>> + of <prgn>prerm</prgn> or other <prgn>postinst</prgn>
>> + actions, the package dependencies will be at least
>> + unpacked or "Half-Installed".
>> + </p>
> I disagree with this change. If you are making use of non-essential
> packages in your postrm, you *should* use the Depends: field; you just
> *also* have to have a clean fallback plan if the dependency is not
> satisfied when the postrm is called.
> The normal use case is "whichever of the two packages is removed first
> must clean up". While I can't think of a case where the cleanup
> interface called from the postrm isn't already a dependency for other
> reasons (e.g., for use in the postinst), I'd like this to be explicit
> all the same.
How about this?
The <tt>Depends</tt> field should also be used if the
<prgn>postinst</prgn> or <prgn>prerm</prgn> scripts
require the depended-on package to be unpacked or
configured in order to run, or if the dependend-on package
is desirable for cleanup done by <prgn>postrm</prgn>. In
the case of <tt>postinst configure</tt>, the depended-on
packages will be unpacked and configured first. (If both
packages are involved in a dependency loop, this might not
work as expected; see the explanation a few paragraphs
back.) In the case of <prgn>prerm</prgn> or
other <prgn>postinst</prgn> actions, the package
dependencies will normally be at least unpacked, but they
may be only "Half-Installed" if a previous upgrade of the
dependency failed. In the case of <prgn>postrm</prgn>,
there are no guarantees, but the depended-on package is
more likely to be available if the package declares a
dependency (particularly for <tt>postrm remove</tt>).
The <prgn>postrm</prgn> script must cleanly skip actions
that require a dependency if that dependency isn't
Russ Allbery (email@example.com) <http://www.eyrie.org/~eagle/>