ソースを参照

dpkg: Fix trigger dependency checks and cycle detection

Break dependency cycles on dependtry > 1 in trigproc(), before calling
dependencies_ok(). But if we have a dependency cycle where a package A
awaits triggers and package P has them pending, and both depend on each
other, the dependency cycle breaking code is not smart enough to break
it at the correct place, as the relationship is directional. So we handle
it specially on deppossi_ok_found(), in case we are in the cycle breaking
dependtry. Otherwise we just defer it, but do not record that it can be
fixed by trigger processing, because we would get into an inifite loop.

Move trigger cycle detection after dependency checks, so that it does
not detect bogus trigger cycles that would have been avoided simply by
the dependency checks and cycle breaking code.

Regression introduced in commit 35c1c59cfad75d75b3d98974ad201f95d932adb6.

Closes: #765434, #765668, #765734, #765781, #765789, #765952
Guillem Jover 11 年 前
コミット
e121d882c9
共有3 個のファイルを変更した28 個の追加3 個の削除を含む
  1. 3 0
      debian/changelog
  2. 18 0
      src/packages.c
  3. 7 3
      src/trigproc.c

+ 3 - 0
debian/changelog

@@ -13,6 +13,9 @@ dpkg (1.17.19) UNRELEASED; urgency=low
     Prompted by Helmut Grohne <helmut@subdivi.de>.
   * Reverse --verify-format logic to actually accept 'rpm' as valid.
     Closes: #765907
+  * Fix trigger dependency checks and cycle detection.
+    Regression introduced in dpkg 1.17.17.
+    Closes: #765434, #765668, #765734, #765781, #765789, #765952
 
   [ Updated programs translations ]
   * Italian (Milo Casagrande): Closes: #765748

+ 18 - 0
src/packages.c

@@ -414,6 +414,24 @@ deppossi_ok_found(struct pkginfo *possdependee, struct pkginfo *requiredby,
         debug(dbg_depcondetail, "      triggers-awaited, no fixbytrig");
         goto unsuitable;
       }
+      /* If we have a dependency cycle where a package A awaits trigger
+       * processing and package P has them pending, and both depend on each
+       * other, the dependency cycle breaking code is not smart enough to
+       * break it at the correct place, as the relationship is directional.
+       * So we handle it specially here.
+       *
+       * Otherwise we just defer it, but do not record that it can be fixed
+       * by trigger processing, because we would get into an inifite loop. */
+      if (requiredby == possdependee->trigaw.head->pend) {
+        if (dependtry > 1) {
+          debug(dbg_depcondetail, "      triggers-awaited, fixed by us, "
+                                  "break cycle so ok and found");
+          return FOUND_OK;
+        } else {
+          debug(dbg_depcondetail, "      triggers-awaited, fixed by us, defer");
+          return FOUND_DEFER;
+        }
+      }
       /* We don't check the status of trigaw.head->pend here, just in case
        * we get into the pathological situation where Triggers-Awaited but
        * the named package doesn't actually have any pending triggers. In

+ 7 - 3
src/trigproc.c

@@ -332,9 +332,9 @@ trigproc(struct pkginfo *pkg)
 		assert(pkg->status == PKG_STAT_TRIGGERSPENDING ||
 		       pkg->status == PKG_STAT_TRIGGERSAWAITED);
 
-		gaveup = check_trigger_cycle(pkg);
-		if (gaveup == pkg)
-			return;
+		if (dependtry > 1)
+			if (findbreakcycle(pkg))
+				sincenothing = 0;
 
 		ok = dependencies_ok(pkg, NULL, &depwhynot);
 		if (ok == DEP_CHECK_OK) {
@@ -356,6 +356,10 @@ trigproc(struct pkginfo *pkg)
 			return;
 		}
 
+		gaveup = check_trigger_cycle(pkg);
+		if (gaveup == pkg)
+			return;
+
 		printf(_("Processing triggers for %s (%s) ...\n"),
 		       pkg_name(pkg, pnaw_nonambig),
 		       versiondescribe(&pkg->installed.version, vdew_nonambig));