瀏覽代碼

libdpkg: Register all pending triggers for deferred processing

Trigger processing on the deferred stage is just opportunistic, but
we enqueue all currently pending triggers that might have been
activated on a previous unpack run, only when being called as
«dpkg --configure pkgname…».

This is a mostly conformant workaround for frontends like apt that do
not correctly call «dpkg --configure -a» or «dpkg --triggers-only -a»
after their normal runs, and leave packages in triggers-pending and
triggers-awaited states.

Closes: #766758
Guillem Jover 11 年之前
父節點
當前提交
75a857d79d
共有 4 個文件被更改,包括 47 次插入0 次删除
  1. 5 0
      debian/changelog
  2. 1 0
      src/main.h
  3. 3 0
      src/packages.c
  4. 38 0
      src/trigproc.c

+ 5 - 0
debian/changelog

@@ -28,6 +28,11 @@ dpkg (1.17.22) UNRELEASED; urgency=low
     should only fail on the former but ignore the latter. Closes: #768852
     should only fail on the former but ignore the latter. Closes: #768852
   * Do not ignore trigger cycles for direct dependencies, these are just
   * Do not ignore trigger cycles for direct dependencies, these are just
     normal trigger cycles, and as such should not be special cased.
     normal trigger cycles, and as such should not be special cased.
+  * Register all pending triggers for deferred processing when being called
+    as «dpkg --configure pkgname…». This is a mostly conformant workaround
+    for frontends like apt that do not correctly call «dpkg --configure -a»
+    or «dpkg --triggers-only -a» after their normal runs, and leave packages
+    in triggers-pending and triggers-awaited states. Closes: #766758
 
 
   [ Updated programs translations ]
   [ Updated programs translations ]
   * German (Sven Joachim).
   * German (Sven Joachim).

+ 1 - 0
src/main.h

@@ -280,6 +280,7 @@ enum trigproc_type {
 };
 };
 
 
 void trigproc_install_hooks(void);
 void trigproc_install_hooks(void);
+void trigproc_populate_deferred(void);
 void trigproc_run_deferred(void);
 void trigproc_run_deferred(void);
 void trigproc_reset_cycle(void);
 void trigproc_reset_cycle(void);
 
 

+ 3 - 0
src/packages.c

@@ -128,6 +128,9 @@ enqueue_specified(const char *const *argv)
     }
     }
     enqueue_package_mark_seen(pkg);
     enqueue_package_mark_seen(pkg);
   }
   }
+
+  if (cipaction->arg_int == act_configure)
+    trigproc_populate_deferred();
 }
 }
 
 
 int
 int

+ 38 - 0
src/trigproc.c

@@ -103,6 +103,44 @@ trigproc_enqueue_deferred(struct pkginfo *pend)
 	      pkg_name(pend, pnaw_always));
 	      pkg_name(pend, pnaw_always));
 }
 }
 
 
+/**
+ * Populate the deferred trigger queue.
+ *
+ * When dpkg is called with a specific set of packages to act on, we might
+ * have packages pending trigger processing. But because there are frontends
+ * that do not perform a final «dpkg --configure --pending» call (i.e. apt),
+ * the system is left in a state with packages not fully installed.
+ *
+ * We have to populate the deferred trigger queue from the entire package
+ * database, so that we might try to do opportunistic trigger processing
+ * when going through the deferred trigger queue, because a fixed apt will
+ * not request the necessary processing anyway.
+ *
+ * XXX: This can be removed once apt is fixed in the next stable release.
+ */
+void
+trigproc_populate_deferred(void)
+{
+	struct pkgiterator *iter;
+	struct pkginfo *pkg;
+
+	iter = pkg_db_iter_new();
+	while ((pkg = pkg_db_iter_next_pkg(iter))) {
+		if (!pkg->trigpend_head)
+			continue;
+
+		if (pkg->status != PKG_STAT_TRIGGERSAWAITED &&
+		    pkg->status != PKG_STAT_TRIGGERSPENDING)
+			continue;
+
+		if (pkg->want != PKG_WANT_INSTALL)
+			continue;
+
+		trigproc_enqueue_deferred(pkg);
+	}
+	pkg_db_iter_free(iter);
+}
+
 void
 void
 trigproc_run_deferred(void)
 trigproc_run_deferred(void)
 {
 {