summaryrefslogtreecommitdiff
path: root/apt-pkg
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2020-05-23 16:22:44 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2020-05-24 21:02:35 +0200
commit2ba86f95bfad4ec00a3b99b311d05c158162b25c (patch)
treef73160ad9a1a7e902b5e2aebca2ee2b3ac256a47 /apt-pkg
parent4f71dc657c34915508a9e34b000e1b577931655a (diff)
Allow pkgDepCache to be asked to check internal consistency
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.
Diffstat (limited to 'apt-pkg')
-rw-r--r--apt-pkg/algorithms.cc14
-rw-r--r--apt-pkg/depcache.cc93
-rw-r--r--apt-pkg/depcache.h4
3 files changed, 106 insertions, 5 deletions
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<int>(State.DepState), static_cast<int>(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<int>(State.DepState), static_cast<int>(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<int>(State.DepState), static_cast<int>(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<int>(State.DepState), static_cast<int>(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