This is an automated email from the git hooks/post-receive script.

guillem pushed a commit to branch master
in repository dpkg.

View the commit online:
https://git.dpkg.org/cgit/dpkg/dpkg.git/commit/?id=7f43bf5f93c857bdb419892abfc014a5e9c3c273

commit 7f43bf5f93c857bdb419892abfc014a5e9c3c273
Author: Guillem Jover <[email protected]>
AuthorDate: Tue Nov 6 03:06:33 2018 +0100

    dpkg: Introduce a new dependency try level for trigger processing
    
    The introduction of dependency satisfiability for trigger processing,
    which was in the original spec but not the implementation, there has
    been countless problems with bogus detection of trigger cycles.
    
    The problem is that whenever we try to process triggers for a package,
    we might not be able to due to dependency unsatisfiaiblity, which means
    we have to put the package back into the queue. If we add the state into
    the cycle detection tracker, then multiple visits to these packages will
    hit the cycle detection for artificially generated cycles. But we cannot
    avoid performing the checks because that will miss dynamic cycles coming
    from maintainer scripts, for example.
    
    To avoid most of these problems (while possibly not fixing all potential
    ones), we should delay trigger processsing entirely until we have
    emptied the processing queue as much as possible. We do that by
    introducing a new dependency try level, after the dependency cycle
    breaking one.
    
    We will also make the trigger cycle detection unconditional of the
    dependency try, because for the trigproc try-queued it will not matter
    anymore as we will only ented on higher dependency tries, and for the
    other trigproc types we should not care about any queue-specific
    dependency try level.
    
    Closes: #810724, #854478, #911620
---
 debian/changelog |  5 +++++
 src/main.h       | 13 +++++++++----
 src/packages.c   |  4 ++--
 src/trigproc.c   | 42 +++++++++++++++++++++++++-----------------
 4 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index f0d38635f..6b223549f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -42,6 +42,11 @@ dpkg (1.19.3) UNRELEASED; urgency=medium
     only reset the cycle detection in case we are not bailing out from the
     processing with an error, otherwise we could come back to this package and
     detect an artificial trigger cycle.
+  * dpkg: Introduce a new dependency try level for trigger processing. This
+    completely defers trigger processing until after the dependency cycle
+    breaking level, so to avoid generating artificial trigger cycles, when we
+    end up trying to process triggers with yet unsatisifiable dependencies.
+    Closes: #810724, #854478, #911620
   * Perl modules:
     - Dpkg::Changelog::Debian: Preserve modelines at EOF. Closes: #916056
       Thanks to Chris Lamb <[email protected]> for initial test cases.
diff --git a/src/main.h b/src/main.h
index c60ccfab0..ff6d4364b 100644
--- a/src/main.h
+++ b/src/main.h
@@ -238,17 +238,22 @@ void deferred_configure(struct pkginfo *pkg);
  *   Find a cycle and break it (see above).
  *   Do as for try 1.
  *
- * Try 3 (only if --force-depends-version):
+ * Try 3:
+ *   Start processing triggers if necessary.
+ *   Do as for try 2.
+ *
+ * Try 4 (only if --force-depends-version):
  *   Same as for try 2, but don't mind version number in dependencies.
  *
- * Try 4 (only if --force-depends):
+ * Try 5 (only if --force-depends):
  *   Do anyway.
  */
 enum dependtry {
        DEPEND_TRY_NORMAL = 1,
        DEPEND_TRY_CYCLES = 2,
-       DEPEND_TRY_FORCE_DEPENDS_VERSION = 3,
-       DEPEND_TRY_FORCE_DEPENDS = 4,
+       DEPEND_TRY_TRIGGERS = 3,
+       DEPEND_TRY_FORCE_DEPENDS_VERSION = 4,
+       DEPEND_TRY_FORCE_DEPENDS = 5,
        DEPEND_TRY_LAST,
 };
 
diff --git a/src/packages.c b/src/packages.c
index d12d8b728..55b56569e 100644
--- a/src/packages.c
+++ b/src/packages.c
@@ -236,8 +236,8 @@ void process_queue(void) {
         internerr("exceeded dependtry %d (sincenothing=%d; queue.length=%d)",
                   dependtry, sincenothing, queue.length);
     } else if (sincenothing > queue.length * 2 + 2) {
-      /* XXX: This probably needs moving into a new dependtry instead. */
-      if (progress_bytrigproc && progress_bytrigproc->trigpend_head) {
+      if (dependtry >= DEPEND_TRY_TRIGGERS &&
+          progress_bytrigproc && progress_bytrigproc->trigpend_head) {
         enqueue_package(pkg);
         pkg = progress_bytrigproc;
         progress_bytrigproc = NULL;
diff --git a/src/trigproc.c b/src/trigproc.c
index 3836c90fa..174683348 100644
--- a/src/trigproc.c
+++ b/src/trigproc.c
@@ -48,10 +48,11 @@
  * we add it to that queue (unless --no-triggers).
  *
  *
- * We want to prefer configuring packages where possible to doing
- * trigger processing, but we want to prefer trigger processing to
- * cycle-breaking and dependency forcing. This is achieved as
- * follows:
+ * We want to prefer configuring packages where possible to doing trigger
+ * processing, although it would be better to prefer trigger processing
+ * to cycle-breaking we need to do the latter first or we might generate
+ * artificial trigger cycles, but we always want to prefer trigger
+ * processing to dependency forcing. This is achieved as follows:
  *
  * Each time during configure processing where a package D is blocked by
  * only (ie Depends unsatisfied but would be satisfied by) a t-awaiter W
@@ -59,10 +60,11 @@
  * (If --no-triggers and nonempty argument list and package isn't in
  * argument list then we don't do this.)
  *
- * Each time in packages.c where we increment dependtry, we instead see
- * if we have encountered such a t-pending T. If we do, we trigproc T
- * instead of incrementing dependtry and this counts as having done
- * something so we reset sincenothing.
+ * Each time in process_queue() where we increment dependtry, we instead
+ * see if we have encountered such a t-pending T. If we do and are in
+ * a trigger processing try, we trigproc T instead of incrementing
+ * dependtry and this counts as having done something so we reset
+ * sincenothing.
  *
  *
  * For --triggers-only and --configure, we go through each thing in the
@@ -390,17 +392,25 @@ trigproc(struct pkginfo *pkg, enum trigproc_type type)
                                  pkg_name(pkg, pnaw_always),
                                  pkg_status_name(pkg));
 
-               if (dependtry >= DEPEND_TRY_CYCLES) {
-                       gaveup = check_trigger_cycle(pkg);
-                       if (gaveup == pkg)
-                               return;
+               if (dependtry < DEPEND_TRY_TRIGGERS &&
+                   type == TRIGPROC_TRY_QUEUED) {
+                       /* We are not yet in a triggers run, so postpone this
+                        * package completely. */
+                       enqueue_package(pkg);
+                       return;
+               }
 
+               if (dependtry >= DEPEND_TRY_CYCLES) {
                        if (findbreakcycle(pkg))
                                sincenothing = 0;
                }
 
                ok = dependencies_ok(pkg, NULL, &depwhynot);
                if (ok == DEP_CHECK_DEFER) {
+                       gaveup = check_trigger_cycle(pkg);
+                       if (gaveup == pkg)
+                               return;
+
                        varbuf_destroy(&depwhynot);
                        enqueue_package(pkg);
                        return;
@@ -435,11 +445,9 @@ trigproc(struct pkginfo *pkg, enum trigproc_type type)
                        varbuf_destroy(&depwhynot);
                }
 
-               if (dependtry < DEPEND_TRY_CYCLES) {
-                       gaveup = check_trigger_cycle(pkg);
-                       if (gaveup == pkg)
-                               return;
-               }
+               gaveup = check_trigger_cycle(pkg);
+               if (gaveup == pkg)
+                       return;
 
                printf(_("Processing triggers for %s (%s) ...\n"),
                       pkg_name(pkg, pnaw_nonambig),

-- 
Dpkg.Org's dpkg

Reply via email to