Re: Bug#582109: debian-policy: document triggers where appropriate
Hi Raphaël,
thanks for the quick feedback.
In the list of directives, I have moved the "noawait" variant on top to
better show that they are the default choice. I also reworded your suggestion
to make it a positive recommenation: use "interest" and "activate" only
if you want to put the triggering package in "Trigger-Awaited" state.
Le Sat, May 11, 2013 at 03:09:25PM +0200, Raphael Hertzog a écrit :
>
> > + <p>
> > + The <file>triggers</file> control file contains one directive per
> > + line. Leading and trailing whitespace, everything after the first
> > + hash character (<tt>#</tt>) on any line, and empty lines are ignored.
> > + The following directives are supported.
> > + <taglist>
> > + <tag><tt>interest</tt> <var>trigger-name</var></tag>
> > + <tag><tt>interest-noawait</tt> <var>trigger-name</var></tag>
> > + <item>
> > + Specifies that the package is interested in the named trigger.
> > + The <tt>interest-noawait</tt> variant does not put the
> > + triggering packages in the "Triggers-Awaited" state.
> > + </item>
> > +
> > + <tag><tt>activate</tt> <var>trigger-name</var></tag>
> > + <tag><tt>activate-noawait</tt> <var>trigger-name</var></tag>
> > + <item>
> > + Specifies that changes to this package's state will activate the
> > + named trigger. The <tt>activate-noawait</tt> variant does not
> > + put this package in the "Triggers-Awaited" state.
> > + </item>
> > + </taglist>
> > + </p>
>
> Here I would add a small paragraph recommending the usage of the -noawait
> variants unless they are strictly required.
>
> <p>The <tt>*-noawait</tt> directives should be used by default to avoid
> putting packages in the "Trigger-Awaited" status. Packages should only end up
> in this intermediary status when they are effectively broken until the
> awaited triggers have been processed. A package in "Trigger-Awaited" does
> not satisfy dependencies, for this reason an excessive and injustified amount of package
> in this status can lead to early processing of triggers or even to dependency
> loops.</p>
Here is my proposition:
<heading>Syntax</heading>
<p>
The <file>triggers</file> control file contains one directive per
line. Leading and trailing whitespace, everything after the first
hash character (<tt>#</tt>) on any line, and empty lines are ignored.
The following directives are supported.
<taglist>
<tag><tt>interest-noawait</tt> <var>trigger-name</var></tag>
<tag><tt>interest</tt> <var>trigger-name</var></tag>
<item>
Specifies that the package is interested in the named trigger.
The <tt>interest</tt> variant puts the triggering packages in
the "Triggers-Awaited" state, and the <tt>interest-noawait</tt>
variant does not.
</item>
<tag><tt>activate-noawait</tt> <var>trigger-name</var></tag>
<tag><tt>activate</tt> <var>trigger-name</var></tag>
<item>
Specifies that changes to this package's state will activate the
named trigger. The <tt>activate</tt> variant puts this package
in the "Triggers-Awaited" state, and the
<tt>activate-noawait</tt> variant does not.
</item>
</taglist>
</p>
<p>
The <tt>*-noawait</tt> directives should be used unless the
packages awaiting triggers can not satisfy <tt>Depends</tt>
relationships until the triggers have been processed.
In that case, the <tt>interest</tt> or <tt>activate</tt> directives
should be used, as they will put the triggering packges in the
"Triggers-Awaited" state, which does not satisfy dependencies.
Note that pakcages unnecessarly entering this state can cause the
early processing of triggers or even dependency loops.
</p>
I also added "through the <tt>interst</tt> or <tt>activate</tt> directives"
after "When a configured package activates a trigger".
I applied the other changes you proposed as well, with minor rewording:
- <prgn>dpkg</prgn> keeps a list, <tt>Triggers-Awaited</tt> of
- interested packages whose trigger processing is awaited. Every
+ <prgn>dpkg</prgn> keeps a list of interested packages whose trigger
+ processing is awaited, which is stored in the
+ <tt>Triggers-Awaited</tt> field in dpkg's status database. Every
I attached an updated version of the patch.
Cheers,
--
Charles
diff --git a/policy.sgml b/policy.sgml
index 1508231..5d53cff 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -900,9 +900,11 @@ zope.
the package. Other control information files include
the <qref id="sharedlibs-symbols"><file>symbols</file> file</qref>
or <qref id="sharedlibs-shlibdeps"><file>shlibs</file> file</qref>
- used to store shared library dependency information and
+ used to store shared library dependency information,
the <file>conffiles</file> file that lists the package's
- configuration files (described in <ref id="config-files">).
+ configuration files (described in <ref id="config-files">), and the
+ <file>triggers</file> file, wich defines the package's interaction with
+ <prgn>dpkg</prgn>'s <qref id="dpkg-triggers">trigger</qref> system.
</p>
<p>
@@ -3959,6 +3961,51 @@ Checksums-Sha256:
</p>
<p>
+ Dpkg defines the following states for the packages.
+ <taglist>
+ <tag>Not-Installed</tag>
+ <item>
+ The package is not installed on the system.
+ </item>
+
+ <tag>Config-Files</tag>
+ <item>
+ Only the configuration files of the package exist on the system.
+ </item>
+
+ <tag>Half-Installed</tag>
+ <item>
+ The installation of the package has been started, but not
+ completed for some reason.
+ </item>
+
+ <tag>Unpacked</tag>
+ <item>
+ The package is unpacked, but not configured.
+ </item>
+
+ <tag>Half-Configured</tag>
+ <item>
+ The package is unpacked and its configuration or the processing
+ of one of its triggers has not yet completed for some reason.
+ </item>
+
+ <tag>Triggers-Awaited</tag>
+ <item>
+ The package awaits trigger processing by another package.
+ </item>
+
+ <tag>Triggers-Pending</tag>
+ <item>
+ The package has been triggered.
+ </item>
+
+ <tag>Installed</tag>
+ <item>
+ The package is unpacked and configured.
+ </item>
+ </taglist>
+ <p>
Broadly speaking the <prgn>preinst</prgn> is called before
(a particular version of) a package is unpacked, and the
<prgn>postinst</prgn> afterwards; the <prgn>prerm</prgn>
@@ -4106,7 +4153,11 @@ Checksums-Sha256:
are no circular dependencies involved, all package
dependencies will be configured. For behavior in the case
of circular dependencies, see the discussion
- in <ref id="binarydeps">.
+ in <ref id="binarydeps">. Even when called with
+ <tt>configure</tt>, this script must do whatever actions are
+ necessary to deal with any
+ <qref id="dpkg-triggers-intermediate-states">triggers</qref>
+ activations.
</item>
<tag><var>old-postinst</var> <tt>abort-upgrade</tt>
@@ -4141,6 +4192,27 @@ Checksums-Sha256:
from the package dependencies are not available is often the
best approach.
</item>
+
+ <tag><var>postinst</var> <tt>triggered</tt>
+ "<var>trigger-name</var> <var>trigger-name</var> ..."</tag>
+ <item>
+ Process one or more <qref id="dpkg-triggers">triggers</qref> that
+ this package is <em>interested</em> in. In case of failure the
+ package's state becomes "Half-Configured" and the task associated
+ to the trigger processing will be completed by the
+ <tt>postinst configure</tt> during the next package's
+ configuration<footnote>
+ When an interested package has more than one trigger and wants
+ to process them differently, the list of triggers can be
+ examined in a shell script like this:
+ <example>
+case " $2 " in
+*" trigger-name-a "*) process-trigger-a ;;
+esac</example>
+ Generally each trigger name should be tested for separately, as
+ the postinst will often be called for several triggers at once.
+ </footnote>.
+ </item>
</taglist>
</p>
@@ -4694,6 +4766,215 @@ fi
</p>
</sect>
+
+ <sect id="dpkg-triggers">
+ <heading>Dpkg triggers</heading>
+
+ <sect1 id="dpkg-triggers-concepts">
+ <heading>Concepts</heading>
+
+ <p>
+ Dpkg triggers allow packages to monitor events caused by
+ the installation, upgrade or removal of other packages. Monitoring
+ packages are said to be <em>interested</em> in some triggers. On the
+ other side, triggers must be <em>activated</em> to notify the
+ interested package, which is then said to have <em>pending</em>
+ triggers. The activating package (if any) is said to <em>await</em>
+ the processing of the trigger.
+ <p>
+
+ <p>
+ The purpose of this feature is to to avoid duplication of processing
+ logic among packages by implementing it in one package and making
+ sure that all other packages rely on triggers to execute the wanted
+ code.
+ </p>
+
+ <p>
+ Each trigger is named, and at any time zero or more packages may be
+ <em>interested</em> in it. For a package to declare its interest in
+ a trigger, it must include one of the <tt>interest</tt> directives
+ in the <file>triggers</file> file in its control archive.
+ </p>
+ </sect1>
+
+ <sect1 id="dpkg-triggers-syntax">
+ <heading>Syntax</heading>
+
+ <p>
+ The <file>triggers</file> control file contains one directive per
+ line. Leading and trailing whitespace, everything after the first
+ hash character (<tt>#</tt>) on any line, and empty lines are ignored.
+ The following directives are supported.
+ <taglist>
+ <tag><tt>interest-noawait</tt> <var>trigger-name</var></tag>
+ <tag><tt>interest</tt> <var>trigger-name</var></tag>
+ <item>
+ Specifies that the package is interested in the named trigger.
+ The <tt>interest</tt> variant puts the triggering packages in
+ the "Triggers-Awaited" state, and the <tt>interest-noawait</tt>
+ variant does not.
+ </item>
+
+ <tag><tt>activate-noawait</tt> <var>trigger-name</var></tag>
+ <tag><tt>activate</tt> <var>trigger-name</var></tag>
+ <item>
+ Specifies that changes to this package's state will activate the
+ named trigger. The <tt>activate</tt> variant puts this package
+ in the "Triggers-Awaited" state, and the
+ <tt>activate-noawait</tt> variant does not.
+ </item>
+ </taglist>
+ </p>
+
+ <p>
+ The <tt>*-noawait</tt> directives should be used unless the
+ packages awaiting triggers can not satisfy <tt>Depends</tt>
+ relationships until the triggers have been processed.
+ In that case, the <tt>interest</tt> or <tt>activate</tt> directives
+ should be used, as they will put the triggering packges in the
+ "Triggers-Awaited" state, which does not satisfy dependencies.
+ Note that pakcages unnecessarly entering this state can cause the
+ early processing of triggers or even dependency loops.
+ </p>
+
+ <p>
+ There are currently two kinds of triggers.
+ <taglist>
+ <tag>Explicit triggers</tag>
+ <item>
+ These can be activated by any program by running
+ <prgn>dpkg-trigger</prgn> (at any time, but ideally from a
+ maintainer script), and by state changes of packages having an
+ <em>activate</em> directive in their <file>triggers</file>
+ control file.
+ </item>
+
+ <tag>File triggers</tag>
+ <item>
+ These are activated automatically by <prgn>dpkg</prgn> when a
+ matching file or directory is created, upgraded or deleted as
+ part of a package's unpacking or removal. They may also be
+ explicitly activated by running
+ <prgn>dpkg-trigger</prgn><footnote>
+ Trigger activation due to a particular file should not
+ generally modify that file again. If there are directory
+ symlinks which result in packages referring to files by
+ different names, then to be sure of activation all of the
+ paths which might be included in packages should be listed.
+ The path specified by the interested package is matched
+ against the path included in the triggering package, not
+ against the true name of the file as installed. Only
+ textually identical filenames (or filenames where the interest
+ is a directory prefix of the installed file) are guaranteed
+ to match.</footnote>.
+ </item>
+ </taglist>
+ </p>
+
+ <p>
+ The name of a file trigger is composed of US-ASCII characters
+ excluding control characters and space (i.e., characters in the
+ range 33-126, inclusive). The names of file triggers is an absolute
+ path to a file or a directory. The names of explicit triggers have
+ the same syntax as package names, but should not be identical to a
+ package name<footnote>
+ When choosing an explicit trigger name it is usually good to
+ include a relevant package name or some other useful identifier
+ to help make the trigger name unique. On the other hand,
+ explicit triggers should generally not be renamed just because
+ the interested or triggering packages' names change.
+ </footnote>.
+ </p>
+ </sect1>
+
+ <sect1 id="dpkg-triggers-mechanims">
+ <heading>Mechanism</heading>
+
+ <p>
+ Triggers are processed by running the interested packages'
+ <tt>postinst</tt> script with the <tt>triggered</tt> parameter (see
+ <ref id="mscriptsinstact">). This will be attempted for each
+ relevant package at the end of each <prgn>dpkg</prgn> run (unless
+ <tt>--no-triggers</tt> has been used); so, normally, in the same dpkg
+ run as the event which marked the package "Triggers-Pending".
+ </p>
+
+ <p>
+ When a configured package activates a trigger through the
+ <tt>interest</tt> or <tt>activate</tt> directives, its state becomes
+ "Triggers-Awaited" instead of "Installed". For this package,
+ <prgn>dpkg</prgn> keeps a list of interested packages whose trigger
+ processing is awaited, which is stored in the
+ <tt>Triggers-Awaited</tt> field in dpkg's status database. Every
+ package in this list either has a nonempty list of pending
+ triggers, or is in "Half-Configured" or worse. When a package in
+ the state "Triggers-Pending" becomes "Installed", "Config-Files" or
+ "Not-Installed", its entry is removed from the
+ <tt>Triggers-Awaited</tt> lists of other packages.
+ </p>
+
+ <p>
+ When a trigger is activated, the state of every interested package
+ becomes "Triggers-Pending". For each package, <prgn>dpkg</prgn>
+ keeps a list keeps a list of interested packages whose trigger
+ processing is pending, which is stored in the
+ <tt>Triggers-Pending</tt> field in dpkg's status database.
+ Repeated activation of the same trigger has no additional effect.
+ In general a trigger will not be processed immediately when it is
+ activated; processing is deferred until it is convenient.
+ </p>
+
+ <p>
+ Packages in the state "Triggers-Pending" that activate a trigger
+ become "Triggers-Awaited". If a package has nonempty
+ <tt>Triggers-Awaited</tt> and <tt>Triggers-Pending</tt> lists, then
+ its state is "Triggers-Awaited". Nevertheless efforts will still
+ be made to process its triggers so as to empty the
+ <tt>Triggers-Pending</tt> list. When a package in the state
+ "Triggers-Awaited" no longer awaits any packages, it becomes
+ "Installed" or "Triggers-Pending".
+ </p>
+
+ <p>
+ Packages should be written so that they do not break just because
+ their pending triggers have not yet been run. It is allowed for the
+ functionality relating to the unprocessed trigger to fail (ie, the
+ package which is awaiting the trigger processing may be broken), but
+ the remainder of the interested package must work normally.
+ </p>
+ </sect1>
+
+ <sect1 id="dpkg-triggers-intermediate-states">
+ <heading>The case of packages in intermediate states</heading>
+
+ <p>
+ Packages in "Config-Files" or "Not-Installed" do not await triggers.
+ </p>
+
+ <p>
+ Packages in "Half-Configured" or worse never have pending triggers.
+ A package is only guaranteed to become notified of a trigger
+ activation if it is continuously interested in the trigger, and never
+ in "Half-Configured" or worse. A package whose postinst is being run
+ can however acquire pending triggers during that run (ie, a package
+ can trigger itself).
+ </p>
+
+ <p>
+ However, if such a package (between "Half-Installed" and
+ "Half-Configured" inclusive) declares some trigger interests then the
+ triggering packages will await their configuration (which implies
+ completion of any necessary trigger processing) or removal.
+ </p>
+
+ <p>
+ For this reason, the <tt>postinst</tt> scripts must do whatever
+ actions are necessary to deal with any trigger activations when they
+ are called with <tt>configure</tt>.
+ </p>
+ </sect1>
+ </sect>
</chapt>
@@ -4978,7 +5259,8 @@ Build-Depends: foo [linux-any], bar [any-i386], baz [!linux-any]
<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
+ configure</tt> and <tt>postinst triggered</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
@@ -8097,8 +8379,8 @@ Reloading <var>description</var> configuration...done.
<p>
The <package>mime-support</package> package provides the
<prgn>update-mime</prgn> program, which integrates these
- registrations in the <file>/etc/mailcap</file> file, using dpkg
- triggers<footnote>
+ registrations in the <file>/etc/mailcap</file> file, using
+ <qref id="dpkg-triggers">dpkg triggers</qref><footnote>
Creating, modifying or removing a file in
<file>/usr/lib/mime/packages/</file> using maintainer scripts will
not activate the trigger. In that case, it can be done by calling
Reply to: