tags 143307 + patch
thanks

I've reproduced the problem from #143307 and attached is a fix.

The core of the problem was that if dpkg is interrupted, you can have
the following situation:

    Package: a
    Triggers-Awaited: b

    Package: b
    Status: ... installed

This is as expected but I obviously hadn't properly tested the
recovery, which is to do a no-op trigger processing step for b.  The
machinery in packages.c would be unimpressed by b's appearance in
progress_bytrigproc.

In the patch below I also fix --no-act for trigger processing, which
was previously broken.  This was somewhat more complex than ideal
because the triggers arrangements leak somewhat more into dbmodify
than previously existing functionality.  I decided to create a new
msdbrw_... value `simulate' and change the various places to use it
and treat it appropriately.  After calling modstatdb_init with
msdbrw_simulate it is permitted to call modstatdb_note.

Ian.


diff --exclude='*~' -bru orig/dpkg-1.14.20/lib/dbmodify.c 
dpkg-1.14.20/lib/dbmodify.c
--- orig/dpkg-1.14.20/lib/dbmodify.c    2008-06-18 08:33:27.000000000 +0100
+++ dpkg-1.14.20/lib/dbmodify.c 2008-06-28 15:41:17.000000000 +0100
@@ -170,8 +170,8 @@
                 msdbrw_write);
     }
     break;
-  case msdbrw_readonly:
-    cstatus= msdbrw_readonly; break;
+  case msdbrw_readonly: case msdbrw_simulate:
+    cstatus= readwritereq; break;
   default:
     internerr("unknown readwritereq");
   }
@@ -204,6 +204,7 @@
 void modstatdb_checkpoint(void) {
   int i;
 
+  if (cstatus == msdbrw_simulate) return;
   assert(cstatus >= msdbrw_write);
   writedb(statusfile,0,1);
   
@@ -249,7 +250,7 @@
 void modstatdb_note(struct pkginfo *pkg) {
   struct trigaw *ta;
 
-  assert(cstatus >= msdbrw_write);
+  assert(cstatus >= msdbrw_simulate);
 
   onerr_abort++;
 
@@ -267,6 +268,8 @@
              versiondescribe(&pkg->installed.version, vdew_nonambig));
   statusfd_send("status: %s: %s", pkg->name, statusinfos[pkg->status].name);
 
+  if (cstatus >= msdbrw_write) {
+
   varbufreset(&uvb);
   varbufrecord(&uvb, pkg, &pkg->installed);
   if (fwrite(uvb.buf, 1, uvb.used, importanttmp) != uvb.used)
@@ -274,7 +277,8 @@
   if (fflush(importanttmp))
     ohshite(_("unable to flush updated status of `%.250s'"), pkg->name);
   if (ftruncate(fileno(importanttmp), uvb.used))
-    ohshite(_("unable to truncate for updated status of `%.250s'"), pkg->name);
+      ohshite(_("unable to truncate for updated status of `%.250s'"),
+             pkg->name);
   if (fsync(fileno(importanttmp)))
     ohshite(_("unable to fsync updated status of `%.250s'"), pkg->name);
   if (fclose(importanttmp))
@@ -282,7 +286,8 @@
   sprintf(updatefnrest, IMPORTANTFMT, nextupdate);
   if (rename(importanttmpfile, updatefnbuf))
     ohshite(_("unable to install updated status of `%.250s'"), pkg->name);
-  assert(strlen(updatefnrest)<=IMPORTANTMAXLEN); /* or we've made a real mess 
*/
+    assert(strlen(updatefnrest)<=IMPORTANTMAXLEN);
+      /* ... or we've made a real mess */
 
   nextupdate++;  
 
@@ -293,6 +298,8 @@
 
   createimptmp();
 
+  }
+
   if (!pkg->trigpend_head && pkg->othertrigaw_head) {
     /* Automatically remove us from other packages' Triggers-Awaited.
      * We do this last because we want to maximise our chances of
diff --exclude='*~' -bru orig/dpkg-1.14.20/lib/dpkg-db.h 
dpkg-1.14.20/lib/dpkg-db.h
--- orig/dpkg-1.14.20/lib/dpkg-db.h     2008-06-18 08:33:27.000000000 +0100
+++ dpkg-1.14.20/lib/dpkg-db.h  2008-06-28 15:41:17.000000000 +0100
@@ -189,6 +189,7 @@
   /* Those marked with \*s*\ are possible returns from modstatdb_init. */
   msdbrw_readonly/*s*/, msdbrw_needsuperuserlockonly/*s*/,
   msdbrw_writeifposs,
+  msdbrw_simulate/*s*/, /* read only, but writes ignored not asserted */
   msdbrw_write/*s*/, msdbrw_needsuperuser,
   /* Now some optional flags: */
   msdbrw_flagsmask= ~077,
diff --exclude='*~' -bru orig/dpkg-1.14.20/lib/triglib.c 
dpkg-1.14.20/lib/triglib.c
--- orig/dpkg-1.14.20/lib/triglib.c     2008-06-18 08:33:27.000000000 +0100
+++ dpkg-1.14.20/lib/triglib.c  2008-06-28 15:45:23.000000000 +0100
@@ -664,9 +664,17 @@
 void
 trig_incorporate(enum modstatdb_rw cstatus, const char *admindir)
 {
+       static int simulation_done;
+
        int ur;
        enum trigdef_updateflags tduf;
 
+       if (cstatus == msdbrw_simulate) {
+               /* only incorporate once, as we're supposed to fold it into 
status */
+               if (simulation_done) return;
+               simulation_done= 1;
+       }
+
        trigdef = &tdm_incorp;
        trig_file_interests_ensure();
 
diff --exclude='*~' -bru orig/dpkg-1.14.20/src/archives.c 
dpkg-1.14.20/src/archives.c
--- orig/dpkg-1.14.20/src/archives.c    2008-06-18 08:33:31.000000000 +0100
+++ dpkg-1.14.20/src/archives.c 2008-06-28 15:41:17.000000000 +0100
@@ -1087,7 +1087,7 @@
   trigproc_install_hooks();
 
   modstatdb_init(admindir,
-                 f_noact ?                     msdbrw_readonly
+                 f_noact ?                     msdbrw_simulate
                : cipaction->arg == act_avail ? msdbrw_write
                : fc_nonroot ?                  msdbrw_write
                :                               msdbrw_needsuperuser);
diff --exclude='*~' -bru orig/dpkg-1.14.20/src/packages.c 
dpkg-1.14.20/src/packages.c
--- orig/dpkg-1.14.20/src/packages.c    2008-06-18 08:33:31.000000000 +0100
+++ dpkg-1.14.20/src/packages.c 2008-06-28 15:54:24.000000000 +0100
@@ -93,7 +93,7 @@
   trigproc_install_hooks();
 
   modstatdb_init(admindir,
-                 f_noact ?    msdbrw_readonly
+                 f_noact ?    msdbrw_simulate
                : fc_nonroot ? msdbrw_write
                :              msdbrw_needsuperuser);
   checkpath();
@@ -211,7 +211,12 @@
     action_todo = cipaction->arg;
 
     if (sincenothing++ > queue.length * 2 + 2) {
-      if (progress_bytrigproc && progress_bytrigproc->trigpend_head) {
+      if (progress_bytrigproc &&
+         (progress_bytrigproc->trigpend_head ||
+          (progress_bytrigproc->status >= stat_triggersawaited &&
+           progress_bytrigproc->othertrigaw_head))) {
+       debug(dbg_depcon, "using progress_bytrigproc %s instead of %s",
+             progress_bytrigproc->name, pkg->name);
         add_to_queue(pkg);
         pkg = progress_bytrigproc;
         action_todo = act_configure;
@@ -246,7 +251,8 @@
       /* Fall through. */
     case act_configure:
       /* Do whatever is most needed. */
-      if (pkg->trigpend_head)
+      if (pkg->trigpend_head ||
+         (pkg->status >= stat_triggersawaited && pkg->othertrigaw_head))
         trigproc(pkg);
       else
         deferred_configure(pkg);
@@ -389,7 +395,7 @@
        * anyway, and that trigger processing will be a noop except for
        * sorting out all of the packages which name it in T-Awaited.
        *
-       * (This situation can only arise if modstatdb_note success in
+       * (This situation can only arise if modstatdb_note succeeds in
        * clearing the triggers-pending status of the pending package
        * but then fails to go on to update the awaiters.)
        */
@@ -609,8 +615,13 @@
   }
   if (ok == 0 && (pkg->clientdata && pkg->clientdata->istobe == itb_remove))
     ok= 1;
-  if (!anycannotfixbytrig && canfixbytrig)
+
+  if (!anycannotfixbytrig && canfixbytrig) {
+    debug(dbg_depcon, "progress_bytrigproc %s (was %s)",
+         canfixbytrig->name,
+         progress_bytrigproc ? progress_bytrigproc->name : "<none>");
     progress_bytrigproc = canfixbytrig;
+  }
   
   varbuffree(&oemsgs);
   debug(dbg_depcon,"ok %d msgs >>%.*s<<", ok, (int)aemsgs->used, aemsgs->buf);
diff --exclude='*~' -bru orig/dpkg-1.14.20/src/trigproc.c 
dpkg-1.14.20/src/trigproc.c
--- orig/dpkg-1.14.20/src/trigproc.c    2008-05-05 18:07:01.000000000 +0100
+++ dpkg-1.14.20/src/trigproc.c 2008-06-28 15:47:05.000000000 +0100
@@ -288,6 +288,7 @@
                printf(_("Processing triggers for %s ...\n"), pkg->name);
                log_action("trigproc", pkg);
 
+               if (!f_noact) {
                varbufreset(&namesarg);
                for (tp = pkg->trigpend_head; tp; tp = tp->next) {
                        varbufaddc(&namesarg, ' ');
@@ -301,6 +302,7 @@
                sincenothing = 0;
                maintainer_script_postinst(pkg, "triggered",
                                           namesarg.buf + 1, NULL);
+               }
 
                /* This is to cope if the package triggers itself: */
                pkg->status = pkg->trigaw.head ? stat_triggersawaited :
diff --exclude='*~' -bru orig/dpkg-1.14.20/src/update.c 
dpkg-1.14.20/src/update.c
--- orig/dpkg-1.14.20/src/update.c      2008-05-05 18:07:01.000000000 +0100
+++ dpkg-1.14.20/src/update.c   2008-06-28 15:41:17.000000000 +0100
@@ -101,7 +101,7 @@
 
   if (*argv) badusage(_("--forget-old-unavail takes no arguments"));
 
-  modstatdb_init(admindir, f_noact ? msdbrw_readonly : msdbrw_write);
+  modstatdb_init(admindir, f_noact ? msdbrw_simulate : msdbrw_write);
 
   it= iterpkgstart();
   while ((pkg= iterpkgnext(it))) {
Only in dpkg-1.14.20: x.gdb




-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to