From 93e1565796b61eb44bec39f50e09a34cbe090178 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Wed, 26 Feb 2020 20:31:03 +0100 Subject: apt(8): Wait for frontend and cache lock This is a rework of !6 with additional stuff for the frontend lock, so we can lock the frontend lock and then keep looping over dpkg lock. --- apt-pkg/deb/debsystem.cc | 50 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) (limited to 'apt-pkg/deb/debsystem.cc') diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc index 225761e9d..da7ae2e42 100644 --- a/apt-pkg/deb/debsystem.cc +++ b/apt-pkg/deb/debsystem.cc @@ -19,8 +19,10 @@ #include #include #include +#include #include +#include #include #include @@ -75,7 +77,42 @@ debSystem::~debSystem() // --------------------------------------------------------------------- /* This mirrors the operations dpkg does when it starts up. Note the checking of the updates directory. */ -bool debSystem::Lock() +static int GetLockMaybeWait(std::string const &file, OpProgress *Progress, int &timeoutSec) +{ + int fd = -1; + if (timeoutSec == 0 || Progress == nullptr) + return GetLock(file); + + if (_config->FindB("Debug::Locking", false)) + std::cerr << "Lock: " << file << " wait " << timeoutSec << std::endl; + + for (int i = 0; timeoutSec < 0 || i < timeoutSec; i++) + { + _error->PushToStack(); + fd = GetLock(file); + if (fd != -1 || errno == EPERM) + { + if (timeoutSec > 0) + timeoutSec -= i; + _error->MergeWithStack(); + return fd; + } + std::string poppedError; + std::string completeError; + _error->PopMessage(poppedError); + _error->RevertToStack(); + + strprintf(completeError, _("Waiting for cache lock (%s)"), poppedError.c_str()); + sleep(1); + Progress->OverallProgress(i, timeoutSec, 0, completeError); + } + + if (timeoutSec > 0) + timeoutSec = 1; + return fd; +} + +bool debSystem::Lock(OpProgress *const Progress) { // Disable file locking if (_config->FindB("Debug::NoLocking",false) == true || d->LockCount > 0) @@ -84,10 +121,12 @@ bool debSystem::Lock() return true; } + // This will count downwards. + int lockTimeOutSec = _config->FindI("DPkg::Lock::Timeout", 0); // Create the lockfile string AdminDir = flNotFile(_config->FindFile("Dir::State::status")); string FrontendLockFile = AdminDir + "lock-frontend"; - d->FrontendLockFD = GetLock(FrontendLockFile); + d->FrontendLockFD = GetLockMaybeWait(FrontendLockFile, Progress, lockTimeOutSec); if (d->FrontendLockFD == -1) { if (errno == EACCES || errno == EAGAIN) @@ -97,7 +136,7 @@ bool debSystem::Lock() return _error->Error(_("Unable to acquire the dpkg frontend lock (%s), " "are you root?"),FrontendLockFile.c_str()); } - if (LockInner() == false) + if (LockInner(Progress, lockTimeOutSec) == false) { close(d->FrontendLockFD); return false; @@ -126,9 +165,10 @@ bool debSystem::Lock() return true; } -bool debSystem::LockInner() { +bool debSystem::LockInner(OpProgress *const Progress, int timeOutSec) +{ string AdminDir = flNotFile(_config->FindFile("Dir::State::status")); - d->LockFD = GetLock(AdminDir + "lock"); + d->LockFD = GetLockMaybeWait(AdminDir + "lock", Progress, timeOutSec); if (d->LockFD == -1) { if (errno == EACCES || errno == EAGAIN) -- cgit v1.2.3-70-g09d2