Steve Langasek wrote: > On Wed, Jul 21, 2010 at 01:52:50PM -0700, Russ Allbery wrote:
>> 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". Yes. It is a case like the avoidance of “inflammable”. Sometimes people need an answer from policy without enough time to think about etymology. >> + 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. Your phrasing is more straightforward. I prefer removed over uninstalled because the corresponding dpkg action is “dpkg --remove”. Anyway, such a change throughout policy would be a separate topic. > Does dpkg provide any guarantee that the dependencies of the pre-dependency > are also present at this point? Sure: that is part of what it means to configure a package. Except *new* dependencies of an upgraded pre-depedency may not be present. This is part of the philosophy behind pseudo-essential packages generally using pre-depends for one release when they acquire new dependencies. > 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. Should I file a policy bug to clarify this? >> + <tag><var>postinst</var> <tt>configure</tt> [...] >> 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? Maybe something as simple as “(See also <ref id="binarydeps">)”. >> + 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. Hopefully Russ can say something useful on this. My guess is “make sure you error out with an appropriate message if functionality from a dependency fails”. That way, the recovery process can error out and the operator can deal with the problem, for example by reinstalling the dependency. Instead, let me mention how rare this problem should be in practice: the problem we are describing is that an upgrade (for a dependency) can be interrupted in the middle of unpacking. dpkg unpacks in three stages: first it writes some temporary files, then a storm of renames, then deletion of removed files. The problem we are describing is that the renames (or deletions) can be interrupted in the middle. The impact is that some files might be from the old version and others from the new version of the dependency. As luck has it, most packages still Just Work™ in this scenario. > 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? Maybe something to this effect: With luck, such a partially upgraded package would still work fine, but maintainer scripts should be prepared to report and error out on resulting errors if they occur. If there is a way to test this automatically (an enhancement to piuparts, maybe?), that would be ideal. [...] >> + 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. [...] > 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 Yes, that is worth mentioning. Actually it has very little to do with dependencies. For example, many packages only use “Suggests: doc-base” but have snippets like the following in prerm: # Automatically added by dh_installdocs if [ "$1" = remove ] || [ "$1" = upgrade ] && \ which install-docs >/dev/null 2>&1; then install-docs -r whatever fi Maybe a footnote would be appropriate? Something along these lines: This is not intended to excuse packages from the obligation to clean up after themselves when they have placed some state in a non-essential package's care. The usual strategy for that is as follows: If you have a package that manages a configuration file with ucf, you must call "ucf --purge" from postrm if ucf is present on the system at that point. If ucf is not present, then the configuration file is in its care and will be removed when ucf is purged. > --> 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. I’ve tried to incorporate this text below. >> @@ -4588,12 +4651,17 @@ Build-Depends: foo [linux-any], bar [any-i386], baz >> [!linux-any] >> >> <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. >> + <prgn>postinst</prgn> or <prgn>prerm</prgn> scripts >> + require the depended-on package to be unpacked or >> + configured in order to run. [...] > I disagree with this change. [...] > 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. Given the explanation above, do you still think Depends should be used this way? > The rest looks good to me. Thanks for the review. Suggested changes follow; thoughts welcome. -- 8< -- Subject: Further improvements to maintainer script state requirements Based on feedback from Steve Langasek. --- Should be applicable to bug504880-rra with “git am -i --scissors”. diff --git a/policy.sgml b/policy.sgml index 20c0c84..9bfb652 100644 --- a/policy.sgml +++ b/policy.sgml @@ -1081,7 +1081,7 @@ <p> Sometimes, unpacking one package requires that another package be first unpacked <em>and</em> configured. In this case, the - dependent package must specify this dependency in + depending package must specify this dependency in the <tt>Pre-Depends</tt> control field. </p> @@ -3791,11 +3791,11 @@ Checksums-Sha256: 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. + available. Pre-dependencies will have been configured at + least once, but at the time the <prgn>preinst</prgn> script + 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 since then. </item> <tag><var>old-preinst</var> <tt>abort-upgrade</tt> @@ -3829,6 +3829,7 @@ Checksums-Sha256: package dependencies will at least be unpacked. If there are no circular dependencies involved, all package dependencies will be configured. + (See also <ref id="binarydeps">.) </item> <tag><var>old-postinst</var> <tt>abort-upgrade</tt> @@ -3848,12 +3849,20 @@ Checksums-Sha256: will have previously been configured and not removed. However, dependencies may not be configured or even fully 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". + <p> + 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". + </p> + + <p> + With luck, the partially upgraded dependency would still + work fine, but <prgn>postinst</prgn> should be prepared to + report and error out on resulting errors when they occur. + </p> </footnote> </item> </taglist> @@ -3911,7 +3920,21 @@ Checksums-Sha256: 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. + the package's dependencies are available.<footnote> + <p> + This is not intended to excuse packages from the + obligation to clean up after themselves when they have + placed some state in a non-essential package's care. + The usual strategy for that is as follows: + </p> + <p> + If you have a package that manages a configuration file + with ucf, you must call "ucf --purge" from postrm if + ucf is present on the system at that point. + If ucf is not present, then the configuration file is + in its care and will be removed when ucf is purged. + </p> + </footnote> </item> <tag><var>new-postrm</var> <tt>failed-upgrade</tt> @@ -4645,9 +4668,16 @@ Build-Depends: foo [linux-any], bar [any-i386], baz [!linux-any] script, then the cycle will be broken at that package; this ensures that all <prgn>postinst</prgn> scripts are run with their dependencies properly configured if this is possible. - Otherwise the breaking point is arbitrary. Packages should - therefore avoid circular dependencies where possible, - particularly if they have <prgn>postinst</prgn> scripts. + Otherwise the breaking point is arbitrary. + </p> + + <p> + 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. + Packages should therefore avoid circular dependencies where + possible, particularly if they have <prgn>postinst</prgn> scripts. </p> <p> -- -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org