From 2ba86f95bfad4ec00a3b99b311d05c158162b25c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 23 May 2020 16:22:44 +0200 Subject: Allow pkgDepCache to be asked to check internal consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For speed reasons pkgDepCache initializes its state once and then has a battery of update calls you have to invoke in the right order to update the various states – all in the name of speed. In debug and/or simulation mode we can sacrifice this speed for a bit of extra checking though to verify that we haven't made some critical mistake like #961266. --- apt-pkg/algorithms.cc | 14 ++++++++ apt-pkg/depcache.cc | 93 ++++++++++++++++++++++++++++++++++++++++++++++++--- apt-pkg/depcache.h | 4 +++ 3 files changed, 106 insertions(+), 5 deletions(-) (limited to 'apt-pkg') diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc index f000b7f39..3fdb5116e 100644 --- a/apt-pkg/algorithms.cc +++ b/apt-pkg/algorithms.cc @@ -58,6 +58,8 @@ pkgSimulate::pkgSimulate(pkgDepCache *Cache) : pkgPackageManager(Cache), string Jnk = "SIMULATE"; for (decltype(PackageCount) I = 0; I != PackageCount; ++I) FileNames[I] = Jnk; + + Cache->CheckConsistency("simulate"); } /*}}}*/ // Simulate::~Simulate - Destructor /*{{{*/ @@ -721,6 +723,9 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) { pkgDepCache::ActionGroup group(Cache); + if (Debug) + Cache.CheckConsistency("resolve start"); + // Record which packages are marked for install bool Again = false; do @@ -1152,6 +1157,8 @@ bool pkgProblemResolver::ResolveInternal(bool const BrokenFix) } } + if (Debug) + Cache.CheckConsistency("resolve done"); return true; } @@ -1211,6 +1218,9 @@ bool pkgProblemResolver::ResolveByKeepInternal() { pkgDepCache::ActionGroup group(Cache); + if (Debug) + Cache.CheckConsistency("keep start"); + MakeScores(); /* We have to order the packages so that the broken fixing pass @@ -1341,6 +1351,10 @@ bool pkgProblemResolver::ResolveByKeepInternal() } delete[] PList; + + if (Debug) + Cache.CheckConsistency("keep done"); + return true; } /*}}}*/ diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index fa0bd8ed5..aa10d8282 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -118,6 +118,88 @@ pkgDepCache::~pkgDepCache() delete delLocalPolicy; } /*}}}*/ +bool pkgDepCache::CheckConsistency(char const *const msgtag) /*{{{*/ +{ + auto const OrigPkgState = PkgState; + auto const OrigDepState = DepState; + + PkgState = new StateCache[Head().PackageCount]; + DepState = new unsigned char[Head().DependsCount]; + memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount); + memset(DepState,0,sizeof(*DepState)*Head().DependsCount); + + auto const origUsrSize = iUsrSize; + auto const origDownloadSize = iDownloadSize; + auto const origInstCount = iInstCount; + auto const origDelCount = iDelCount; + auto const origKeepCount = iKeepCount; + auto const origBrokenCount = iBrokenCount; + auto const origPolicyBrokenCount = iPolicyBrokenCount; + auto const origBadCount = iBadCount; + + for (PkgIterator I = PkgBegin(); not I.end(); ++I) + { + auto &State = PkgState[I->ID]; + auto const &OrigState = OrigPkgState[I->ID]; + State.iFlags = OrigState.iFlags; + + State.CandidateVer = OrigState.CandidateVer; + State.InstallVer = OrigState.InstallVer; + State.Mode = OrigState.Mode; + State.Update(I,*this); + State.Status = OrigState.Status; + } + PerformDependencyPass(nullptr); + + _error->PushToStack(); +#define APT_CONSISTENCY_CHECK(VAR,STR) \ + if (orig##VAR != i##VAR) \ + _error->Warning("Internal Inconsistency in pkgDepCache: " #VAR " " STR " vs " STR " (%s)", i##VAR, orig##VAR, msgtag) + APT_CONSISTENCY_CHECK(UsrSize, "%lld"); + APT_CONSISTENCY_CHECK(DownloadSize, "%lld"); + APT_CONSISTENCY_CHECK(InstCount, "%lu"); + APT_CONSISTENCY_CHECK(DelCount, "%lu"); + APT_CONSISTENCY_CHECK(KeepCount, "%lu"); + APT_CONSISTENCY_CHECK(BrokenCount, "%lu"); + APT_CONSISTENCY_CHECK(PolicyBrokenCount, "%lu"); + APT_CONSISTENCY_CHECK(BadCount, "%lu"); +#undef APT_CONSISTENCY_CHECK + + for (PkgIterator P = PkgBegin(); not P.end(); ++P) + { + auto const &State = PkgState[P->ID]; + auto const &OrigState = OrigPkgState[P->ID]; + if (State.Status != OrigState.Status) + _error->Warning("Internal Inconsistency in pkgDepCache: Status of %s is %d vs %d (%s)", P.FullName().c_str(), State.Status, OrigState.Status, msgtag); + if (State.NowBroken() != OrigState.NowBroken()) + _error->Warning("Internal Inconsistency in pkgDepCache: Now broken for %s is %d vs %d (%s)", P.FullName().c_str(), static_cast(State.DepState), static_cast(OrigState.DepState), msgtag); + if (State.NowPolicyBroken() != OrigState.NowPolicyBroken()) + _error->Warning("Internal Inconsistency in pkgDepCache: Now policy broken for %s is %d vs %d (%s)", P.FullName().c_str(), static_cast(State.DepState), static_cast(OrigState.DepState), msgtag); + if (State.InstBroken() != OrigState.InstBroken()) + _error->Warning("Internal Inconsistency in pkgDepCache: Install broken for %s is %d vs %d (%s)", P.FullName().c_str(), static_cast(State.DepState), static_cast(OrigState.DepState), msgtag); + if (State.InstPolicyBroken() != OrigState.InstPolicyBroken()) + _error->Warning("Internal Inconsistency in pkgDepCache: Install broken for %s is %d vs %d (%s)", P.FullName().c_str(), static_cast(State.DepState), static_cast(OrigState.DepState), msgtag); + } + + auto inconsistent = _error->PendingError(); + _error->MergeWithStack(); + + delete[] PkgState; + delete[] DepState; + PkgState = OrigPkgState; + DepState = OrigDepState; + iUsrSize = origUsrSize; + iDownloadSize = origDownloadSize; + iInstCount = origInstCount; + iDelCount = origDelCount; + iKeepCount = origKeepCount; + iBrokenCount = origBrokenCount; + iPolicyBrokenCount = origPolicyBrokenCount; + iBadCount = origBadCount; + + return not inconsistent; +} + /*}}}*/ // DepCache::Init - Generate the initial extra structures. /*{{{*/ // --------------------------------------------------------------------- /* This allocats the extension buffers and initializes them. */ @@ -655,8 +737,8 @@ void pkgDepCache::UpdateVerState(PkgIterator const &Pkg) // --------------------------------------------------------------------- /* This will figure out the state of all the packages and all the dependencies based on the current policy. */ -void pkgDepCache::Update(OpProgress * const Prog) -{ +void pkgDepCache::PerformDependencyPass(OpProgress * const Prog) +{ iUsrSize = 0; iDownloadSize = 0; iInstCount = 0; @@ -666,7 +748,6 @@ void pkgDepCache::Update(OpProgress * const Prog) iPolicyBrokenCount = 0; iBadCount = 0; - // Perform the depends pass int Done = 0; for (PkgIterator I = PkgBegin(); I.end() != true; ++I, ++Done) { @@ -699,10 +780,12 @@ void pkgDepCache::Update(OpProgress * const Prog) UpdateVerState(I); AddStates(I); } - if (Prog != 0) Prog->Progress(Done); - +} +void pkgDepCache::Update(OpProgress * const Prog) +{ + PerformDependencyPass(Prog); readStateFile(Prog); } /*}}}*/ diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index ff1b37374..d9bb69a18 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -502,6 +502,8 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace pkgDepCache(pkgCache * const Cache,Policy * const Plcy = 0); virtual ~pkgDepCache(); + bool CheckConsistency(char const *const msgtag = ""); + protected: // methods call by IsInstallOk bool IsInstallOkMultiArchSameVersionSynced(PkgIterator const &Pkg, @@ -521,6 +523,8 @@ class APT_PUBLIC pkgDepCache : protected pkgCache::Namespace APT_HIDDEN bool MarkInstall_StateChange(PkgIterator const &Pkg, bool AutoInst, bool FromUser); APT_HIDDEN bool MarkInstall_DiscardInstall(PkgIterator const &Pkg); + + APT_HIDDEN void PerformDependencyPass(OpProgress * const Prog); }; #endif -- cgit v1.2.3