[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [PATCH 4/6] Hook conffile database into dpkg unpack/configure/remove stages



Hi Sean,

I finally got around to reviewing your patch to maintain the conffile
database during unpack/configure/remove stages.  I am still worried
that the “commit” operation does not seem to be atomic like it should
be.  Could you look at my description of your patch and let me know
where I go wrong?

As is, of course, your code should be low-risk, since the conffile
database is not used except as a staging area during unpacking at this
point.  We just have to check that the database is well enough
maintained that future patches can rely on it.

Okay, so here’s what your patch does:

 * Before unpacking, clean out the staged ("new") version of a
   package’s conffile database.

 * When unpacking archives, let conffiles pass through the staged
   (new) conffile database before copying to their installed location
   elsewhere in the filesystem.

 * When configuring, “commit” the package’s staged conffile database
   (rename it to "current").

 * When purging a package’s configuration files, remove its conffile
   database (right after removing the conffiles themselves).

This all seems sane and simple --- good.

Invariants maintained (ignoring a possible tmp conffile db):

 * When not-installed, a package has no conffile db.

 * In config-files state, a package has a "current" conffile db
   and no other.

 * When half-installed, a package has no conffile db.

 * Once unpacked, a package may or may not have a "current"
   conffile db, which remembers the distributed configuration files
   for the last configured version; and a package will certainly have
   a "new" conffile db, which holds the distributed configuration
   files for the unpacked version.

 * In half-configured state, everything breaks.  It is possible
   to forget the "current" conffile db here.  One problem is that
   committing the new conffile db requires multiple steps:

	rm -r tmp/pkg
	mv current/pkg tmp/pkg
	mv new/pkg current/pkg
	rm -r tmp/pkg

   If dpkg is interrupted in the middle, the "current" configuration
   can be lost.

	$ dpkg --configure pkg
	rm -r tmp/pkg
	mv current/pkg tmp/pkg
	<dpkg is interrupted here>
	$ # okay, better try again.
	$ dpkg --configure pkg
	rm -r tmp/pkg
	...

    If dpkg is interrupted after committing the new conffile db but
    before the package leaves half-configured state, the "new"
    configuration can be lost.

	$ dpkg --configure pkg
	rm -r tmp/pkg
	mv current/pkg tmp/pkg
	mv new/pkg current/pkg
	rm -r tmp/pkg
	<dpkg is interrupted here>
	$ # okay, better try again.
	$ dpkg --configure pkg
	rm -r tmp/pkg
	mv current/pkg tmp/pkg
	[dpkg could notice something wrong here: why is new missing?]
	mv new/pkg current/pkg
	rm -r tmp/pkg
	<dpkg is interrupted>
	$ # okay, try again
	rm -r tmp/pkg
	...

   One (crazy?) idea would be to overwrite entries in current/pkg
   until they all match new/.  That is, run the equivalent of

	ln -f new/pkg/afd9834287dc... current/pkg/afd9834287dc...

   for each configuration file until their stat information matches.

   Upside: I imagine something similar to this would be useful anyway
   for remembering which configuration files have been brought up to
   date.  Downside: after this operation, the old distributed
   configuration file is gone.  There is no turning back and deciding
   to upgrade the conffile a different way.

 - Once installed, the "current" conffile db should remember
   the distributed configuration files and there should be no
   "new" conffile db.

 - triggers-awaited and triggers-pending are just like the
   installed state here.

What do you think?

Thanks for the interesting read.  Hopefully, others can chime in with
some more useful thoughts.

Regards,
Jonathan


Reply to: