[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#504880: Disambiguate "installed" for packages



Hi,

Russ Allbery wrote:

> This adds new information to the "Summary of ways maintainer scripts are
> called" section (6.5) stating exactly what maintainer scripts can depend
> on when various actions are called.

This is very welcome.  Thanks for moving it forward.

Warning: most of what I say below is with reference to the old version
of policy, not the dpkg source.  So please check with someone more
reliable before taking anything I say as a given.

> +++ b/policy.sgml
> @@ -3758,111 +3758,166 @@ Checksums-Sha256:
>  	</heading>
>  
>  	<p>
> +	  What follows is a summary of all the ways in which maintainer
> +	  scripts may be called along with what facilities those scripts
> +	  may rely on being available at that time.  Script names
> +	  preceeded by <var>new-</var> are the scripts from the new
> +	  version of a package being installed or upgraded.  Script names
> +	  preceeded by <var>old-</var> are the scripts from the old
> +	  version of a package that is being upgraded to a new version.
> +	</p>

Spelling: “preceeded” should be “preceded”.

The term “upgraded” is a bit ambiguous in situations where a package is
being downgraded or an upgrade is being rolled back.  Probably the
context makes the meaning obvious in any particular instance, though.

> +
> +	<p>
> +	  The <prgn>preinst</prgn> script may be called in the following
> +	  ways:
> -	  <list compact="compact">
> -	    <item>
> -	      <var>new-preinst</var> <tt>install</tt>
> -	    </item>
> -	    <item>
> -	      <var>new-preinst</var> <tt>install</tt> <var>old-version</var>
> -	    </item>
> -	    <item>
> -		<var>new-preinst</var> <tt>upgrade</tt> <var>old-version</var>
> -	    </item>
> +	  <taglist>
> +	    <tag><var>new-preinst</var> <tt>install</tt></tag>
> +	    <tag><var>new-preinst</var> <tt>install</tt>
> +	      <var>old-version</var></tag>
> +	    <tag><var>new-preinst</var> <tt>upgrade</tt>
> +	      <var>old-version</var></tag>
> +	    <item>
> +	      Only essential packages and pre-dependencies
> +	      (<tt>Pre-Depends</tt>) may be assumed to be available.
> +	      Pre-dependencies will either be configured or will be
> +	      "Unpacked" or "Half-Configured" but previously had been
> +	      configured and was never removed.

The second sentence is starting to get wordy.  Maybe:

	Only essential packages and pre-dependencies
	(<tt>Pre-Depends</tt>) may be assumed to be available.
	Pre-dependencies will be unpacked and have been
	configured after they were last removed[1].

	[1] During an upgrade, a package listed in
	<tt>Pre-Depends</tt> may be "Unpacked" or "Half-Configured"
	in its new version, but only if a previous version was
	configured completely and the package has not been
	removed since then.

I doubt these rules apply to the initial bootstrap.  Is that worth
mentioning somewhere?

>                                                The package will not yet
> +	      be unpacked, so the <prgn>preinst</prgn> script cannot rely
> +	      on any files included in its package.
> +	    </item>
> +
> -	    <item>
> -		<var>old-preinst</var> <tt>abort-upgrade</tt>
> -		<var>new-version</var>
> -	    </item>
> -	  </list>
> -
> +	    <tag><var>old-preinst</var> <tt>abort-upgrade</tt>
> +	      <var>new-version</var></tag>
> +	    <item>
> +	      Called during error handling of an upgrade that failed after
> +	      unpacking the new package because the
> +	      old <prgn>postrm</prgn> failed during the upgrade action.

Getting wordy.  Maybe:

	Called to recover from an upgrade that failed after
	unpacking the new package because the old <prgn>postrm</prgn>
	failed.

> +	      Depending on the severity and nature of the error, the
> +	      package's dependencies, including pre-dependencies, may be
> +	      only "Half-Installed" or "Unpacked" and are not necessarily
> +	      configured, and the files for the old package may not yet be
> +	      unpacked.
> +	    </item>
> +	  </taglist>
> +	</p>

 * Not sure what the phrase “Depending on the ... nature of the
   error” is supposed to be getting at here.  Is this just to say
   the package might not have been fully installed yet?  I would
   leave the clause out.

 * Can’t (new) dependencies be missing altogether?  I thought part of
   the point of the pre-depends/depends distinction was that the
   latter does not constrain unpacking order.

 * Could old (removed) dependencies be missing altogether, too?
   Sure: if I unpack one version of the package and then try to
   unpack the next and that fails, ...

 * postrm does not get called until pre-dependencies for the new
   version are satisfied.  So I think it is impossible for
   pre-dependencies to be half-installed here.

 * As usual in the halfinstalled state, files from both the
   new and the old package may be missing.

So:

	Pre-dependencies for the old and new versions of the package
	will be at least unpacked and have been configured after they
	were last removed[1].

	The package's dependencies (<tt>Depends</tt>) in the new and
	old versions are not guaranteed to be satisfied, and files
	from the old and new versions of the package are neither
	guaranteed to be present nor not present in the file system.

In particular, it is not so pleasant to imagine, but given:

 packagea, version 1: Pre-Depends: packageb
 packagea, version 2: Pre-Depends: packagec
 packagec: Conflicts: packageb

I think frontends/dpkg will correctly error out.

Another edge case involves replaces (packagec could make packageb
disappear), but that is a topic for another day.

> -	<p>
> -	  <list compact="compact">
> -	    <item>
> -		<var>postinst</var> <tt>configure</tt>
> -		<var>most-recently-configured-version</var>
> -	    </item>
> +
> +	<p>
> +	  The <prgn>postinst</prgn> script may be called in the following
> +	  ways:
> +	  <taglist>
> +	    <tag><var>postinst</var> <tt>configure</tt>
> +	      <var>most-recently-configured-version</var></tag>
> +	    <item>
> +	      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.
> +	    </item>

Nice.

[...]
> +	    <tag><var>old-postinst</var> <tt>abort-upgrade</tt>
> +	      <var>new-version</var></tag>
> +	    <tag><var>conflictor's-postinst</var> <tt>abort-remove</tt>
> +	      <tt>in-favour</tt> <var>package</var>
> +	      <var>new-version</var></tag>
> +	    <tag><var>postinst</var> <tt>abort-remove</tt></tag>
> +	    <tag><var>deconfigured's-postinst</var>
> +	      <tt>abort-deconfigure</tt> <tt>in-favour</tt>
> +	      <var>failed-install-package</var> <var>version</var>
> +	      [<tt>removing</tt> <var>conflicting-package</var>
> +	      <var>version</var>]</tag>
> +	    <item>
> +	      The files contained in the package will be unpacked.  All
> +	      package dependencies will at least be "Half-Installed" and
> +	      will have previously been configured and not removed.
> +	      However, depending on the nature and severity of the error,
> +	      dependencies may not be configured or even fully unpacked.
> +	    </item>
> +	  </taglist>
> +	</p>

An example of when dependencies can be half-installed would be
helpful.

For example, where packagea depends on packageb:

	dpkg --install packagea_1.deb packageb_1.deb

	dpkg --unpack packageb_2.deb
	^C; # now packageb is halfinstalled

	dpkg --remove packagea

Now if prerm fails, then postinst abort-remove will be called
with packageb halfinstalled.

Notice:

 * Dependencies are always checked when dpkg --configure (or
   dpkg --install) is run for a package without --force-depends.
   The only interesting cases are:

    - aborting a removal
    - aborting an upgrade in which a dependency has been dropped

 * If I understand correctly, postinst can rely on Depends satisfying
   the same condition as Pre-Depends usually do: _some_ version
   of the dependent package was once fully installed, and the package
   has not been removed since then.

[...]
> +	  <taglist>
> +	    <tag><var>prerm</var> <tt>remove</tt></tag>
> +	    <tag><var>old-prerm</var>
> +	      <tt>upgrade</tt><var>new-version</var></tag>
> +	    <tag><var>conflictor's-prerm</var> <tt>remove</tt>
> +	      <tt>in-favour</tt> <var>package</var>
> +	      <var>new-version</var></tag>
> +	    <tag><var>deconfigured's-prerm</var> <tt>deconfigure</tt>
> +	      <tt>in-favour</tt> <var>package-being-installed</var>
> +	      <var>version</var> [<tt>removing</tt>
> +	      <var>conflicting-package</var> <var>version</var>]</tag>
> +	    <item>
> +	      The package whose <prgn>prerm</prgn> is being called will be
> +	      at least "Half-Installed".  All package dependencies will at
> +	      least be "Half-Installed" and will have previously been
> +	      configured and not removed.  If there was no error, all
> +	      dependencies will at least be unpacked, but these actions
> +	      may be called in various error states where dependencies are
> +	      only "Half-Installed".
> +	    </item>
> +

Any package we call prerm for is halfconfigured or better, so all
of its dependencies were fully satisfied at some point.

Like before, it is probably worth mentioning that dependencies can
only be halfinstalled in this case due to a partial upgrade, not a
partial install.

> +	    <tag><var>new-prerm</var> <tt>failed-upgrade</tt>
> +	      <var>old-version</var></tag>
> +	    <item>
> +	      Called during error handling when <tt>prerm upgrade</tt>
> +	      fails.  The new package will not yet be unpacked.  Since
> +	      this is the first action taken during a package upgrade,
> +	      only essential packages and pre-dependencies may be relied
> +	      on.  Pre-dependencies will either be configured or will be
> +	      "Unpacked" or "Half-Configured" but previously had been
> +	      configured and was never removed.
> +	    </item>
> +	  </taglist>
> +	</p>

Why can’t one rely on dependencies here, too?

[...]
> -	    <item>
> -		<var>old-postrm</var> <tt>upgrade</tt>
> -		<var>new-version</var>
> -	    </item>
> +
> +	<p>
> +	  The <prgn>postrm</prgn> script may be called in the following
> +	  ways:
> +	  <taglist>
> +	    <tag><var>postrm</var> <tt>remove</tt></tag>
> +	    <tag><var>postrm</var> <tt>purge</tt></tag>
> +	    <tag><var>old-postrm</var> <tt>upgrade</tt>
> +	      <var>new-version</var></tag>
> +	    <tag><var>disappearer's-postrm</var> <tt>disappear</tt>
> +		<var>overwriter</var> <var>overwriter-version</var></tag>
> +	    <item>
> +	      The <prgn>postrm</prgn> script is called after the package's
> +	      files have been removed.  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.
> +	    </item>

Yes.

For upgrade, the new package will be unpacked already, right?  Maybe
that should be discussed in the same paragraph as failed-upgrade.

[...]
> -	    <item>
> -		<var>new-postrm</var> <tt>abort-install</tt>
> -	    </item>
> -	    <item>
> -		<var>new-postrm</var> <tt>abort-install</tt>
> -		<var>old-version</var>
> -	    </item>
> -	    <item>
> -		<var>new-postrm</var> <tt>abort-upgrade</tt>
> -		<var>old-version</var>
> -	    </item>
> -	    <item>
> -		<var>disappearer's-postrm</var> <tt>disappear</tt>
> -		<var>overwriter</var>
> -		<var>overwriter-version</var>
> -	    </item>
> -	  </list>
> +
> +	    <tag><var>new-postrm</var> <tt>abort-install</tt></tag>
> +	    <tag><var>new-postrm</var> <tt>abort-install</tt>
> +	      <var>old-version</var></tag>
> +	    <tag><var>new-postrm</var> <tt>abort-upgrade</tt>
> +	      <var>old-version</var></tag>
> +	    <item>
> +	      Called before unpackaging the new package as part of the
> +	      error handling of <prgn>preinst</prgn> failures.  May assume
> +	      the same state as <prgn>preinst</prgn> can assume.
> +	    </item>
> +	  </taglist>
>  	</p>
> -
> +      </sect>

Looks good.

Stopping here.  Will pick up with the rest in a separate message.
Jonathan



Reply to: