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