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

Bug#770291: E: Couldn't configure systemd-sysv:i386, probably a dependency cycle. on apt-get --reinstall install systemd systemd-sysv sysv-rc



Hi,

On Thu, Nov 20, 2014 at 10:16:40AM +0100, Andreas Beckmann wrote:
> In a minimal jessie i386 chroot (created and used by piuparts) with
> systemd, systemd-sysv, sysv-rc installed apt fails on this command:
> 
>     apt-get -u --reinstall install systemd systemd-sysv sysv-rc
[…]
>   E: Couldn't configure systemd-sysv:i386, probably a dependency cycle.

This is actually a fun one (not in absolute values, just by ordering bug
comparison). We can ignore sysv-rc here as it is reproducible without
it. What remains are two (pseudo) essential packages which have
a pre-dependency relation and need to be reinstalled (aka: need to be
considered not installed for all practical proposes).
[you also need systemd to have more pre-dependencies than systemd-sysv]

The problem is that if we deal with systemd first (and as it is
essential we will unpack and configure it) and deal with systemd-sysv
later the pre-depends check fails to recognize that systemd is done.
(in fact, it recognizes that systemd is done, but it doesn't notice that
it was touched by the reinstall so that it believes it is untouched and
hence not part of the solution and therefore expects another or-group
member to be the satisfier here – just that there isn't another or-group
member as there is no or-group here).

I have a patch, which fixes this one and supposely fixes 3 other places
were checks do not consider the reinstall case, but I haven't written
a testcase for them yet, so that is more proof-of-concept than a real
patch. This one here alone might not be jessie-worthy, but with the
three others it might, we will see.
(the attached diff is written against experimental, but just for the
testcase, the code itself should backport cleanly)

Workarounds:
1. Check if --reinstall is really needed here. If you don't randomly
delete files on your system, it isn't too useful…
2. Split the reinstall up to one package at the time.
3. Do the reinstall with dpkg.


Best regards

David Kalnischkies
diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc
index ba48c53..1fb99ea 100644
--- a/apt-pkg/packagemanager.cc
+++ b/apt-pkg/packagemanager.cc
@@ -400,7 +400,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	       // Check if the current version of the package is available and will satisfy this dependency
 	       if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true &&
 		   List->IsFlag(DepPkg,pkgOrderList::Removed) == false &&
-		   DepPkg.State() == PkgIterator::NeedsNothing)
+		   DepPkg.State() == PkgIterator::NeedsNothing &&
+		   (Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
 	       {
 		  Bad = false;
 		  break;
@@ -444,7 +445,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 	       // Check if the current version of the package is available and will satisfy this dependency
 	       if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true &&
 		   List->IsFlag(DepPkg,pkgOrderList::Removed) == false &&
-		   DepPkg.State() == PkgIterator::NeedsNothing)
+		   DepPkg.State() == PkgIterator::NeedsNothing &&
+		   (Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
                   continue;
 
 	       // Check if the version that is going to be installed will satisfy the dependency
@@ -722,7 +724,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
 
 		  // See if the current version is ok
 		  if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true &&
-		      Pkg.State() == PkgIterator::NeedsNothing)
+		      Pkg.State() == PkgIterator::NeedsNothing &&
+		      (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
 		  {
 		     Bad = false;
 		     if (Debug)
@@ -745,7 +748,8 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
 
 		  // Not the install version
 		  if (Cache[DepPkg].InstallVer != *I ||
-		      (Cache[DepPkg].Keep() == true && DepPkg.State() == PkgIterator::NeedsNothing))
+		      (Cache[DepPkg].Keep() == true && DepPkg.State() == PkgIterator::NeedsNothing &&
+		       (Cache[DepPkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall))
 		     continue;
 
 		  if (List->IsFlag(DepPkg,pkgOrderList::Configured))
diff --git a/test/integration/test-bug-770291-reinstall b/test/integration/test-bug-770291-reinstall
new file mode 100755
index 0000000..cfb17ba
--- /dev/null
+++ b/test/integration/test-bug-770291-reinstall
@@ -0,0 +1,27 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'i386'
+
+insertpackage 'unstable,installed' 'libc6' 'i386' '1'
+insertpackage 'unstable,installed' 'libselinux1' 'i386' '1'
+insertpackage 'unstable,installed' 'systemd-sysv' 'i386' '215-5+b1' 'Depends: systemd (= 215-5+b1)
+Pre-Depends: systemd'
+# fun fact: we need these two pre-depends to get systemd ordered before systemd-sysv as
+# many pre-depends mean: do early (as they are a pain, so get them out of the way early)
+insertpackage 'unstable,installed' 'systemd' 'i386' '215-5+b1' 'Pre-Depends: libc6, libselinux1'
+insertpackage 'unstable,installed' 'init' 'i386' '1' 'Depends: systemd-sysv
+Essential: yes'
+
+setupaptarchive
+
+testequal 'Reading package lists...
+Building dependency tree...
+0 upgraded, 0 newly installed, 2 reinstalled, 0 to remove and 0 not upgraded.
+Inst systemd [215-5+b1] (215-5+b1 unstable [i386])
+Conf systemd (215-5+b1 unstable [i386])
+Inst systemd-sysv [215-5+b1] (215-5+b1 unstable [i386])
+Conf systemd-sysv (215-5+b1 unstable [i386])' aptget install --reinstall systemd systemd-sysv -s

Attachment: signature.asc
Description: Digital signature


Reply to: