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/cachefile.cc | 2 +- apt-pkg/deb/debsystem.cc | 50 ++++++++++++++++++++++++++++++++++++----- apt-pkg/deb/debsystem.h | 5 ++--- apt-pkg/edsp/edspsystem.cc | 2 +- apt-pkg/edsp/edspsystem.h | 4 ++-- apt-pkg/pkgsystem.h | 5 +++-- apt-private/private-cmndline.cc | 5 +++++ debian/NEWS | 7 ++++++ doc/examples/configure-index | 2 ++ 9 files changed, 68 insertions(+), 14 deletions(-) diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc index 9a1a6cfa9..8b86fa3e4 100644 --- a/apt-pkg/cachefile.cc +++ b/apt-pkg/cachefile.cc @@ -106,7 +106,7 @@ bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock) if (WithLock == true) { - if (_system->Lock() == false) + if (_system->Lock(Progress) == false) return false; d->WithLock = true; } 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) diff --git a/apt-pkg/deb/debsystem.h b/apt-pkg/deb/debsystem.h index a331af351..2e5a8550c 100644 --- a/apt-pkg/deb/debsystem.h +++ b/apt-pkg/deb/debsystem.h @@ -27,8 +27,7 @@ class debSystem : public pkgSystem APT_HIDDEN bool CheckUpdates(); public: - - virtual bool Lock() APT_OVERRIDE; + virtual bool Lock(OpProgress *const Progress) APT_OVERRIDE; virtual bool UnLock(bool NoErrors = false) APT_OVERRIDE; virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const APT_OVERRIDE; virtual bool Initialize(Configuration &Cnf) APT_OVERRIDE; @@ -48,7 +47,7 @@ class debSystem : public pkgSystem bool MultiArchSupported() const override; std::vector ArchitecturesSupported() const override; - bool LockInner() override; + bool LockInner(OpProgress *const Progress, int timeoutSec) override; bool UnLockInner(bool NoErrors=false) override; bool IsLocked() override; }; diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc index 47f5e06d5..c86f1ed3f 100644 --- a/apt-pkg/edsp/edspsystem.cc +++ b/apt-pkg/edsp/edspsystem.cc @@ -39,7 +39,7 @@ eippSystem::eippSystem() : edspLikeSystem("Debian APT planner interface") } /*}}}*/ // System::Lock - Get the lock /*{{{*/ -bool edspLikeSystem::Lock() +bool edspLikeSystem::Lock(OpProgress *) { return true; } diff --git a/apt-pkg/edsp/edspsystem.h b/apt-pkg/edsp/edspsystem.h index 33f06c4d5..97c2d66e2 100644 --- a/apt-pkg/edsp/edspsystem.h +++ b/apt-pkg/edsp/edspsystem.h @@ -29,7 +29,7 @@ protected: std::unique_ptr StatusFile; public: - virtual bool Lock() APT_OVERRIDE APT_PURE; + virtual bool Lock(OpProgress * const Progress) APT_OVERRIDE APT_PURE; virtual bool UnLock(bool NoErrors = false) APT_OVERRIDE APT_PURE; virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const APT_OVERRIDE APT_PURE; virtual bool Initialize(Configuration &Cnf) APT_OVERRIDE; @@ -41,7 +41,7 @@ public: bool MultiArchSupported() const override { return true; } std::vector ArchitecturesSupported() const override { return {}; }; - bool LockInner() override { return _error->Error("LockInner is not implemented"); }; + bool LockInner(OpProgress * const, int) override { return _error->Error("LockInner is not implemented"); }; bool UnLockInner(bool) override { return _error->Error("UnLockInner is not implemented"); }; bool IsLocked() override { return true; }; diff --git a/apt-pkg/pkgsystem.h b/apt-pkg/pkgsystem.h index dca5747c1..10065d0ce 100644 --- a/apt-pkg/pkgsystem.h +++ b/apt-pkg/pkgsystem.h @@ -46,6 +46,7 @@ class pkgPackageManager; class pkgVersioningSystem; class Configuration; class pkgIndexFile; +class OpProgress; class pkgSystemPrivate; class APT_PUBLIC pkgSystem @@ -62,7 +63,7 @@ class APT_PUBLIC pkgSystem /* Prevent other programs from touching shared data not covered by other locks (cache or state locks) */ - virtual bool Lock() = 0; + virtual bool Lock(OpProgress *const Progress = nullptr) = 0; virtual bool UnLock(bool NoErrors = false) = 0; /* Various helper classes to interface with specific bits of this @@ -124,7 +125,7 @@ class APT_PUBLIC pkgSystem * lock without releasing the overall outer lock, so that dpkg can run * correctly but no other APT instance can acquire the system lock. */ - virtual bool LockInner() = 0; + virtual bool LockInner(OpProgress *const Progress = 0, int timeOutSec = 0) = 0; virtual bool UnLockInner(bool NoErrors = false) = 0; /// checks if the system is currently locked virtual bool IsLocked() = 0; diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index c5edae5d0..478cb95f1 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -475,6 +475,11 @@ static void BinarySpecificConfiguration(char const * const Binary) /*{{{*/ _config->CndSet("Binary::apt::APT::Keep-Downloaded-Packages", false); _config->CndSet("Binary::apt::APT::Get::Update::InteractiveReleaseInfoChanges", true); _config->CndSet("Binary::apt::APT::Cmd::Pattern-Only", true); + + if (isatty(STDIN_FILENO)) + _config->CndSet("Binary::apt::Dpkg::Lock::Timeout", -1); + else + _config->CndSet("Binary::apt::Dpkg::Lock::Timeout", 120); } _config->Set("Binary", binary); diff --git a/debian/NEWS b/debian/NEWS index 35b562dda..3b208f1b0 100644 --- a/debian/NEWS +++ b/debian/NEWS @@ -1,3 +1,10 @@ +apt (1.9.11) UNRELEASED; urgency=medium + + apt(8) now waits for the lock indefinitely if connected to a tty, or + for 120 seconds if not. + + -- Julian Andres Klode Wed, 26 Feb 2020 20:30:33 +0100 + apt (1.9.6) experimental; urgency=medium apt(8) no longer treats package names passed as regular expressions or fnmatch diff --git a/doc/examples/configure-index b/doc/examples/configure-index index cc70465d6..4e0bd57ae 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -551,6 +551,7 @@ Debug InstallProgress::Fancy ""; APT::Progress::PackageManagerFd ""; SetupAPTPartialDirectory::AssumeGood ""; + Locking ""; }; pkgCacheGen @@ -684,6 +685,7 @@ dpkg::selection::remove::approved ""; dpkg::remove::crossgrade::implicit ""; dpkg::selection::current::saveandrestore ""; dpkg::use-pty ""; +dpkg::lock::timeout ""; apt::cmd::disable-script-warning ""; apt::cmd::show-update-stats ""; -- cgit v1.2.3