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

Re: Bug#504880: Disambiguate "installed" for packages



Steve Langasek <vorlon@debian.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.)

Changed.

>> +	      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.
>>  	    </item>

> 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.
>>  	    </item>

> 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>
>>  	    </item>
>> -	  </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
	      best approach.

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:
<example>
if [ "$1" = purge ] && [ -e /usr/share/debconf/confmodule ]; then
        . /usr/share/debconf/confmodule
        db_purge
fi
</example>
		in <prgn>postrm</prgn> purges the <prgn>debconf</prgn>
		configuration for the package
		if <package>debconf</package> is installed.
	      </foonote>

>   --> 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.

Fixed.

>>  	      <p>
>>  		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>
>>  	    </item>

> 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?

	      <p>
		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
		available.
	      </p>

-- 
Russ Allbery (rra@debian.org)               <http://www.eyrie.org/~eagle/>


Reply to: