summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2020-02-26 20:31:03 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2020-02-26 20:36:52 +0100
commit93e1565796b61eb44bec39f50e09a34cbe090178 (patch)
treeebb655eb7496799009b672c39799f670a596eb3e
parentdb678df196ccd8f9f6fb336706cf5701d1e53aa6 (diff)
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.
-rw-r--r--apt-pkg/cachefile.cc2
-rw-r--r--apt-pkg/deb/debsystem.cc50
-rw-r--r--apt-pkg/deb/debsystem.h5
-rw-r--r--apt-pkg/edsp/edspsystem.cc2
-rw-r--r--apt-pkg/edsp/edspsystem.h4
-rw-r--r--apt-pkg/pkgsystem.h5
-rw-r--r--apt-private/private-cmndline.cc5
-rw-r--r--debian/NEWS7
-rw-r--r--doc/examples/configure-index2
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 <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/pkgcache.h>
+#include <apt-pkg/progress.h>
#include <algorithm>
+#include <sstream>
#include <string>
#include <vector>
@@ -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<std::string> 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<pkgIndexFile> 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<std::string> 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 <jak@debian.org> 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 "<BOOL>";
APT::Progress::PackageManagerFd "<BOOL>";
SetupAPTPartialDirectory::AssumeGood "<BOOL>";
+ Locking "<BOOL>";
};
pkgCacheGen
@@ -684,6 +685,7 @@ dpkg::selection::remove::approved "<BOOL>";
dpkg::remove::crossgrade::implicit "<BOOL>";
dpkg::selection::current::saveandrestore "<BOOL>";
dpkg::use-pty "<BOOL>";
+dpkg::lock::timeout "<INT>";
apt::cmd::disable-script-warning "<BOOL>";
apt::cmd::show-update-stats "<BOOL>";