Quellcode durchsuchen

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 vor 11 Jahren
Ursprung
Commit
75a857d79d
4 geänderte Dateien mit 47 neuen und 0 gelöschten Zeilen
  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
   * Do not ignore trigger cycles for direct dependencies, these are just
     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 ]
   * German (Sven Joachim).

+ 1 - 0
src/main.h

@@ -280,6 +280,7 @@ enum trigproc_type {
 };
 
 void trigproc_install_hooks(void);
+void trigproc_populate_deferred(void);
 void trigproc_run_deferred(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);
   }
+
+  if (cipaction->arg_int == act_configure)
+    trigproc_populate_deferred();
 }
 
 int

+ 38 - 0
src/trigproc.c

@@ -103,6 +103,44 @@ trigproc_enqueue_deferred(struct pkginfo *pend)
 	      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
 trigproc_run_deferred(void)
 {