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

Bug#582109: debian-policy: document triggers where appropriate



Le Sat, Aug 03, 2013 at 09:41:59AM -0700, Jonathan Nieder a écrit :
> 
> If I end up with time to work on it, what I would probably do is to
> split the patch into smaller changes that can be considered and
> applied independently, which would hopefully be less intimidating for
> area experts to review.

Hi Jonathan,

I have split the patch in the following parts:

	0001-Document-Dpkg-states.patch
	0002-Document-postinst-triggered.patch
	0003-Document-concepts-syntax-and-control-information-fil.patch
	0004-Detail-the-two-trigger-kinds-explicit-and-file.patch
	0005-Details-about-Dpkg-states-when-processing-triggers.patch
	0006-Document-the-behaviour-of-triggers-when-packages-are.patch

I could not cut in smaller pieces, as it would separate informations that would
lose a lot of context if they are not added together.

> With triggers, one of the hardest parts to document is how packagers
> are supposed to deal with the "dependencies may not be configured"
> bug.  Mentioning the bug as you have is good, but giving some
> practical advice about how to work around it ("Do not rely on a sane
> state being present" is not practical advice because it doesn't say
> what to do when your dependencies are missing) would be better.  Maybe
> policy should only define the -noawait variant for now?

In the current patch, the -noawait variant is recommended.  I think that the
Policy should not hide information about a feature in the hope that less people
use it.  I think that it is important that the Policy stays a neutral
reference.

About the Dpkg bug, I think that we should consider the whole section about the
postinst script.  In the paragraph above the description of "postinst
triggered" it already mentions "consider the correct error handling approach if
those actions fail".  I think that this is also the current practice for
"postinst configure", where often I sed that commands are tested for their
availability before being run.  Lastly, the current patch also mentions
"Pre-Depends", which is a robust last-ressort solution.

In the existing documentation of the dpkg triggers, the bug of dpkg is not
mentionned, so I think that this patch to the Policy represents a progress
compared with the current situation.  I still do not understand why there is so
much reluctance in enhancing our documentation.

Have a nice Sunday,

-- 
Charles Plessy
Tsurumi, Kanagawa, Japan
>From 5d3279e10152d6ecb8b2b4bf226f7e7a380228e1 Mon Sep 17 00:00:00 2001
From: Charles Plessy <plessy@debian.org>
Date: Sun, 4 Aug 2013 07:17:03 +0900
Subject: [PATCH 1/6] Document Dpkg states.

---
 policy.sgml              | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 upgrading-checklist.sgml |  4 ++++
 2 files changed, 51 insertions(+)

diff --git a/policy.sgml b/policy.sgml
index cb1093f..e3598f1 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -3959,6 +3959,53 @@ 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>
+
+	<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>
diff --git a/upgrading-checklist.sgml b/upgrading-checklist.sgml
index 0a111d4..41a1e84 100644
--- a/upgrading-checklist.sgml
+++ b/upgrading-checklist.sgml
@@ -55,6 +55,10 @@ Unreleased.
   <item>New section documenting the <tt>Package-Type</tt> field in source
   package control files.
   </item>
+<tag>6.1</tag>
+  <item>The Dpkg states are now documented.  The Policy has been proofread
+  and occurences of "Failed-Config" have been corrected to "Half-Configured".
+  </item>
 <tag>11.5.2</tag>
   <item>Stop recommending to serve HTML documents from
   <file>/usr/share/doc/<var>package</var></file>.
-- 
1.8.4.rc0

>From e7c1f429ab818b73b20c99605769ca97c5fff2f5 Mon Sep 17 00:00:00 2001
From: Charles Plessy <plessy@debian.org>
Date: Sun, 4 Aug 2013 07:41:39 +0900
Subject: [PATCH 2/6] Document "postinst triggered".

---
 policy.sgml              | 40 ++++++++++++++++++++++++++++++++++++++--
 upgrading-checklist.sgml |  5 +++++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/policy.sgml b/policy.sgml
index e3598f1..f82aa12 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -4153,7 +4153,9 @@ 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 triggers activation.
 	    </item>
 
 	    <tag><var>old-postinst</var> <tt>abort-upgrade</tt>
@@ -4188,6 +4190,39 @@ 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>
+	      <prgn>postinst configure</prgn> was already run and the
+	      dependencies ought to be configured. However, <prgn>dpkg</prgn>
+	      currently suffers of a bug which means that <prgn>postinst
+              triggered</prgn> can be called while some dependencies are being
+	      upgraded (see bug <url id="http://bugs.debian.org/671711";
+	      name="671711">). Until this bug is absent from the stable
+	      release, you should thus only rely on the fact that the
+	      dependencies are at least unpacked and were already configured once
+	      (similar to what <tt>Pre-Depends</tt> ensures for
+	      <prgn>preinst</prgn> maintainer scripts).
+
+	      <prgn>postinst triggered</prgn> processes 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>
 
@@ -5025,7 +5060,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
diff --git a/upgrading-checklist.sgml b/upgrading-checklist.sgml
index 41a1e84..3d41475 100644
--- a/upgrading-checklist.sgml
+++ b/upgrading-checklist.sgml
@@ -59,6 +59,11 @@ Unreleased.
   <item>The Dpkg states are now documented.  The Policy has been proofread
   and occurences of "Failed-Config" have been corrected to "Half-Configured".
   </item>
+<tag>6.5</tag>
+  <item>The <tt>triggered</tt> call for the <var>postinst</var> script is now
+  documented.  <var>postinst</var> <tt>configure</tt> must do whatever actions
+  are necessary to deal with any triggers activation.
+  </item>
 <tag>11.5.2</tag>
   <item>Stop recommending to serve HTML documents from
   <file>/usr/share/doc/<var>package</var></file>.
-- 
1.8.4.rc0

>From 29cbcdd626050b748a667cb01efc450fb248b32b Mon Sep 17 00:00:00 2001
From: Charles Plessy <plessy@debian.org>
Date: Sun, 4 Aug 2013 07:51:25 +0900
Subject: [PATCH 3/6] Document concepts, syntax and control information file
 for dpkg triggers.

---
 policy.sgml              | 83 +++++++++++++++++++++++++++++++++++++++++++++---
 upgrading-checklist.sgml |  3 ++
 2 files changed, 82 insertions(+), 4 deletions(-)

diff --git a/policy.sgml b/policy.sgml
index f82aa12..48c6a5f 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, which defines the package's interaction with
+	<prgn>dpkg</prgn>'s <qref id="dpkg-triggers">trigger</qref> system.
       </p>
 
       <p>
@@ -4776,6 +4778,79 @@ 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 packages in the
+	    "Triggers-Awaited" state, which does not satisfy dependencies.
+	    Note that packages unnecessarily entering this state can cause the
+	    early processing of triggers or even dependency loops.
+	  </p>
+	</sect1>
+      </sect>
     </chapt>
 
 
@@ -8180,8 +8255,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
diff --git a/upgrading-checklist.sgml b/upgrading-checklist.sgml
index 3d41475..ac44278 100644
--- a/upgrading-checklist.sgml
+++ b/upgrading-checklist.sgml
@@ -64,6 +64,9 @@ Unreleased.
   documented.  <var>postinst</var> <tt>configure</tt> must do whatever actions
   are necessary to deal with any triggers activation.
   </item>
+<tag>6.9</tag>
+  <item>New section describing Dpkg triggers.
+  </item>
 <tag>11.5.2</tag>
   <item>Stop recommending to serve HTML documents from
   <file>/usr/share/doc/<var>package</var></file>.
-- 
1.8.4.rc0

>From 5c2454c1a5c11f943de90ff888176be3e7a314e4 Mon Sep 17 00:00:00 2001
From: Charles Plessy <plessy@debian.org>
Date: Sun, 4 Aug 2013 08:38:15 +0900
Subject: [PATCH 4/6] Detail the two trigger kinds, explicit and file.

---
 policy.sgml | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/policy.sgml b/policy.sgml
index 48c6a5f..bfeef28 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -4849,6 +4849,55 @@ fi
 	    Note that packages unnecessarily 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>
       </sect>
     </chapt>
-- 
1.8.4.rc0

>From 666a43b28e2ca2b22e616de5a57aa15cc1e2f8ad Mon Sep 17 00:00:00 2001
From: Charles Plessy <plessy@debian.org>
Date: Sun, 4 Aug 2013 08:45:24 +0900
Subject: [PATCH 5/6] Details about Dpkg states when processing triggers.

---
 policy.sgml | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/policy.sgml b/policy.sgml
index bfeef28..f57df14 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -4899,6 +4899,63 @@ fi
 	    </footnote>.
 	  </p>
 	</sect1>
+
+	<sect1 id="dpkg-triggers-mechanism">
+	<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>
       </sect>
     </chapt>
 
-- 
1.8.4.rc0

>From efc24791c8ed97ace3762ef9fab1da1161918598 Mon Sep 17 00:00:00 2001
From: Charles Plessy <plessy@debian.org>
Date: Sun, 4 Aug 2013 08:50:46 +0900
Subject: [PATCH 6/6] Document the behaviour of triggers when packages are in
 intermediate states.

---
 policy.sgml | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/policy.sgml b/policy.sgml
index f57df14..8360e50 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -4157,7 +4157,9 @@ Checksums-Sha256:
 	      of circular dependencies, see the discussion
 	      in <ref id="binarydeps">.  Even when called with
 	      <tt>configure</tt>, this script must do whatever actions are
-	      necessary to deal with any triggers activation.
+	      necessary to deal with any
+	      <qref id="dpkg-triggers-intermediate-states">triggers</qref>
+	      activation.
 	    </item>
 
 	    <tag><var>old-postinst</var> <tt>abort-upgrade</tt>
@@ -4956,6 +4958,36 @@ fi
 	    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 activation when they
+	    are called with <tt>configure</tt>.
+	  </p>
+	</sect1>
       </sect>
     </chapt>
 
-- 
1.8.4.rc0


Reply to: