>From 9c059705f153135fef1d4585561ce9297583a18d Mon Sep 17 00:00:00 2001
From: Julian Andres Klode <juliank@ubuntu.com>
Date: Sun, 28 Dec 2025 17:33:30 +0100
Subject: [PATCH] Implement frontend locking

Change the aptitude locking to never release the frontend lock
but only the inner lock and change internal calls to dpkg to
tell it when we hold the frontend lock.

Bug-Debian: https://bugs.debian.org/933335
---
 src/generic/apt/aptcache.cc        | 36 ++++++++++++++++++++----------
 src/generic/apt/aptcache.h         |  5 +++--
 src/generic/apt/dpkg_selections.cc |  5 +++++
 3 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/src/generic/apt/aptcache.cc b/src/generic/apt/aptcache.cc
index ea176c13..1bc80c86 100644
--- a/src/generic/apt/aptcache.cc
+++ b/src/generic/apt/aptcache.cc
@@ -2512,7 +2512,7 @@ void aptitudeDepCache::apply_solution(const generic_solution<aptitude_universe>
 }
 
 aptitudeCacheFile::aptitudeCacheFile()
-  :Map(NULL), Cache(NULL), DCache(NULL), have_system_lock(false), Policy(NULL)
+  :Map(NULL), Cache(NULL), DCache(NULL), have_frontend_lock(false), have_inner_lock(false), Policy(NULL)
 {
 }
 
@@ -2537,7 +2537,8 @@ bool aptitudeCacheFile::Open(OpProgress* Progress,
       if(!_system->Lock())
 	return false;
 
-      have_system_lock=true;
+      have_frontend_lock=true;
+      have_inner_lock=true;
     }
 
   if(_error->PendingError())
@@ -2590,24 +2591,35 @@ bool aptitudeCacheFile::Open(OpProgress* Progress,
   return true;
 }
 
+// Release the inner lock. Does not release the frontend lock.
 void aptitudeCacheFile::ReleaseLock()
 {
-  if(have_system_lock)
-    {
-      _system->UnLock();
-      have_system_lock=false;
-    }
+  assert(have_frontend_lock >= have_inner_lock);
+  if (have_inner_lock)
+    _system->UnLockInner();
+  have_inner_lock=false;
 }
 
+// Gains the frontend lock and inner lock
+// The frontend lock is never released again.
 bool aptitudeCacheFile::GainLock()
 {
-  if(have_system_lock)
-    return true;
+  assert(have_frontend_lock >= have_inner_lock);
 
-  if(!_system->Lock())
-    return false;
+  if (!have_frontend_lock)
+    {
+      if(!_system->Lock())
+        return false;
+      have_frontend_lock=true;
+      have_inner_lock=true;
+    }
+  else if (!have_inner_lock)
+    {
+      if(!_system->LockInner())
+        return false;
+      have_inner_lock=true;
+    }
 
-  have_system_lock=true;
   return true;
 }
 
diff --git a/src/generic/apt/aptcache.h b/src/generic/apt/aptcache.h
index 3fe3e301..3322ab36 100644
--- a/src/generic/apt/aptcache.h
+++ b/src/generic/apt/aptcache.h
@@ -560,7 +560,8 @@ class aptitudeCacheFile
   pkgCache *Cache;
   aptitudeDepCache *DCache;
 
-  bool have_system_lock;
+  bool have_frontend_lock;
+  bool have_inner_lock;
   // hm, used to make it look like the old stuff?
 public:
 
@@ -581,7 +582,7 @@ public:
 	    bool WithLock,
 	    const char* status_fname,
 	    bool reset_reinstall);
-  bool is_locked() {return have_system_lock;} // EWW (also not quite right)
+  bool is_locked() {return have_frontend_lock;} // EWW (also not quite right)
 
   void ReleaseLock();
   bool GainLock();
diff --git a/src/generic/apt/dpkg_selections.cc b/src/generic/apt/dpkg_selections.cc
index 34cb3341..5d75780b 100644
--- a/src/generic/apt/dpkg_selections.cc
+++ b/src/generic/apt/dpkg_selections.cc
@@ -23,6 +23,7 @@
 #include "aptitude.h"
 
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/error.h>
 
 #include <cstdlib>
@@ -98,6 +99,10 @@ bool DpkgSelections::save_to_dpkg(const std::string& selections)
       signal(SIGBUS,  SIG_DFL);
       signal(SIGABRT, SIG_DFL);
 
+      // Tell dpkg whether we hold the frontend lock
+      if (_system->IsLocked() == true)
+        setenv("DPKG_FRONTEND_LOCKED", "true", 1);
+
       // set input and output for this process
       dup2(dpkg_pipe[0], STDIN_FILENO);
       int fd_null = open("/dev/null", O_RDONLY);
-- 
2.51.0

