Browse Source

apt-get waits for dpkg lock

Milan Jurkulak 3 months ago
parent
commit
d04df7cdc3
3 changed files with 18 additions and 5 deletions
  1. 9 4
      compositor/compositor.gradle.kts
  2. 4 0
      gradle/libs.versions.toml
  3. 5 1
      make-iso.sh

+ 9 - 4
compositor/compositor.gradle.kts

@@ -168,6 +168,11 @@ tasks.register<Copy>("stageSession") {
 // shared with the deb Depends and make-iso.sh), never hardcoded here.
 // shared with the deb Depends and make-iso.sh), never hardcoded here.
 val compositorRuntimeDeps: String = libs.versions.app.compositor.runtime.deps.get()
 val compositorRuntimeDeps: String = libs.versions.app.compositor.runtime.deps.get()
 
 
+// apt-get on the host must WAIT for the dpkg lock (unattended-upgrades, a parallel build, …)
+// instead of failing with "Could not get lock /var/lib/dpkg/lock-frontend" — catalog-driven.
+val aptLockTimeout: String = libs.versions.app.apt.lock.timeout.get()
+val aptGet = "apt-get -o DPkg::Lock::Timeout=$aptLockTimeout"
+
 fun sessionInstallLines(staged: File): List<String> = listOf(
 fun sessionInstallLines(staged: File): List<String> = listOf(
     "#!/bin/sh",
     "#!/bin/sh",
     "set -e",
     "set -e",
@@ -176,8 +181,8 @@ fun sessionInstallLines(staged: File): List<String> = listOf(
     // pulls libdrm/libgbm/libinput/libseat/libxkbcommon/libwayland/libdisplay-info/libliftoff;
     // pulls libdrm/libgbm/libinput/libseat/libxkbcommon/libwayland/libdisplay-info/libliftoff;
     // xwayland = X display for the AWT-based Compose shell; libgl1-mesa-dri = the GL/EGL driver
     // xwayland = X display for the AWT-based Compose shell; libgl1-mesa-dri = the GL/EGL driver
     // (incl. llvmpipe software fallback). Without these mjdevc fails to even load -> black screen.
     // (incl. llvmpipe software fallback). Without these mjdevc fails to even load -> black screen.
-    "apt-get update || true",
-    "apt-get install --no-install-recommends -y $compositorRuntimeDeps seatd || " +
+    "$aptGet update || true",
+    "$aptGet install --no-install-recommends -y $compositorRuntimeDeps seatd || " +
             "echo 'WARN: apt could not install the wayland runtime stack (offline or non-debian?) — the desktop may not start'",
             "echo 'WARN: apt could not install the wayland runtime stack (offline or non-debian?) — the desktop may not start'",
     // the compositor opens /dev/dri/card0 + the seatd socket (group video); seatd must run and
     // the compositor opens /dev/dri/card0 + the seatd socket (group video); seatd must run and
     // the logged-in user must be in video/input/render (+ seat if present) or the session is black.
     // the logged-in user must be in video/input/render (+ seat if present) or the session is black.
@@ -230,8 +235,8 @@ tasks.register<Exec>("installDesktop") {
         val script = staged.resolve("install-desktop.sh")
         val script = staged.resolve("install-desktop.sh")
         // install the deb via apt so its Depends (the wayland runtime stack baked in by
         // install the deb via apt so its Depends (the wayland runtime stack baked in by
         // packageFullDeb) are resolved; fall back to dpkg + apt -f if the apt form is unavailable.
         // packageFullDeb) are resolved; fall back to dpkg + apt -f if the apt form is unavailable.
-        val installDeb = "apt-get install --no-install-recommends -y '${deb.absolutePath}' || " +
-                "{ dpkg -i '${deb.absolutePath}' || true; apt-get install -f -y; }"
+        val installDeb = "$aptGet install --no-install-recommends -y '${deb.absolutePath}' || " +
+                "{ dpkg -i '${deb.absolutePath}' || true; $aptGet install -f -y; }"
         script.writeText((lines + installDeb).joinToString("\n") + "\n")
         script.writeText((lines + installDeb).joinToString("\n") + "\n")
         // pkexec pops a graphical polkit auth dialog and runs the script as root; needs a polkit
         // pkexec pops a graphical polkit auth dialog and runs the script as root; needs a polkit
         // agent in the session but no terminal. Fall back to a printed sudo command if absent.
         // agent in the session but no terminal. Fall back to a printed sudo command if absent.

+ 4 - 0
gradle/libs.versions.toml

@@ -15,6 +15,10 @@ app-vendor = "mjdev"
 # deb packaging joins it with ", ". A clean/GNOME box lacks these (GNOME uses mutter, not wlroots),
 # deb packaging joins it with ", ". A clean/GNOME box lacks these (GNOME uses mutter, not wlroots),
 # so without them mjdevc fails to load (libwlroots-0.18.so missing) and the session black-screens.
 # so without them mjdevc fails to load (libwlroots-0.18.so missing) and the session black-screens.
 app-compositor-runtime-deps = "libwlroots-0.18 xwayland libegl1 libgles2 libgbm1 libinput10 libseat1 libxkbcommon0 libgl1-mesa-dri dbus dbus-user-session"
 app-compositor-runtime-deps = "libwlroots-0.18 xwayland libegl1 libgles2 libgbm1 libinput10 libseat1 libxkbcommon0 libgl1-mesa-dri dbus dbus-user-session"
+# Seconds apt-get waits for the dpkg lock (/var/lib/dpkg/lock-frontend) instead of failing
+# immediately when another apt/dpkg process holds it (unattended-upgrades, a parallel build, …).
+# Consumed by installDesktop/installSession (compositor.gradle.kts) and make-iso.sh.
+app-apt-lock-timeout = "600"
 java-language-version = "17"
 java-language-version = "17"
 # app specific android
 # app specific android
 android-compile-sdk = "36"
 android-compile-sdk = "36"

+ 5 - 1
make-iso.sh

@@ -24,6 +24,9 @@ VERSION="$(read_catalog app-pkg-version)"
 [ -n "$APP_NAME" ] && [ -n "$VERSION" ] || { echo "cannot read app name/version from $CATALOG"; exit 1; }
 [ -n "$APP_NAME" ] && [ -n "$VERSION" ] || { echo "cannot read app name/version from $CATALOG"; exit 1; }
 # wayland runtime stack for mjdevc — single source of truth in the version catalog (not hardcoded)
 # wayland runtime stack for mjdevc — single source of truth in the version catalog (not hardcoded)
 RUNTIME_DEPS="$(read_catalog app-compositor-runtime-deps)"
 RUNTIME_DEPS="$(read_catalog app-compositor-runtime-deps)"
+# apt-get must wait for the dpkg lock instead of failing ("Could not get lock
+# /var/lib/dpkg/lock-frontend") when another apt/dpkg runs — value from the catalog.
+APT_LOCK_TIMEOUT="$(read_catalog app-apt-lock-timeout)"
 
 
 # ---- config / args -------------------------------------------------------
 # ---- config / args -------------------------------------------------------
 # trixie = Debian 13, the current stable ("latest public version"). A bare
 # trixie = Debian 13, the current stable ("latest public version"). A bare
@@ -97,10 +100,11 @@ mount -t sysfs sys "$ROOT/sys"
 # chroot can reach the mirror (without this apt-get update fails -> exit 100).
 # chroot can reach the mirror (without this apt-get update fails -> exit 100).
 cp -L /etc/resolv.conf "$ROOT/etc/resolv.conf" 2>/dev/null || true
 cp -L /etc/resolv.conf "$ROOT/etc/resolv.conf" 2>/dev/null || true
 
 
-cat > "$ROOT/etc/apt/apt.conf.d/99lean" <<'EOF'
+cat > "$ROOT/etc/apt/apt.conf.d/99lean" <<EOF
 APT::Install-Recommends "false";
 APT::Install-Recommends "false";
 APT::Install-Suggests "false";
 APT::Install-Suggests "false";
 Acquire::Languages "none";
 Acquire::Languages "none";
+DPkg::Lock::Timeout "$APT_LOCK_TIMEOUT";
 EOF
 EOF
 
 
 # stage the desktop app deb, the compositor binary + session files, and every
 # stage the desktop app deb, the compositor binary + session files, and every