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

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: