Bug#990932: unblock: udpkg/1.20
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Please unblock package udpkg
I've added locking for the status file, so parallel udpkg invocations
will not break the world. This fixes #987368. We definitely want this
fix for Bullseye. I've CC:ed KiBi too.
See attached debdiff.
unblock udpkg/1.20
-- System Information:
Debian Release: 10.10
APT prefers stable-debug
APT policy: (500, 'stable-debug'), (500, 'stable'), (500, 'oldstable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 5.10.0-0.bpo.5-amd64 (SMP w/4 CPU cores)
Kernel taint flags: TAINT_CPU_OUT_OF_SPEC
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE=en_GB:en (charmap=UTF-8)
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diff -Nru udpkg-1.19/debian/changelog udpkg-1.20/debian/changelog
--- udpkg-1.19/debian/changelog 2018-09-23 18:16:44.000000000 +0100
+++ udpkg-1.20/debian/changelog 2021-06-11 02:46:39.000000000 +0100
@@ -1,3 +1,19 @@
+udpkg (1.20) unstable; urgency=medium
+
+ [ Holger Wansing ]
+ * Remove trailing whitespaces from changelog file, to fix lintian tag.
+
+ [ Cyril Brulebois ]
+ * Remove Christian Perrier from Uploaders, with many thanks for all
+ his contributions over the years! (Closes: #927557)
+
+ [ Steve McIntyre ]
+ * Add locking for the status file, so parallel udpkg invocations
+ will not break the world. Closes: #987368
+ * Add myself to Uploaders
+
+ -- Steve McIntyre <93sam@debian.org> Fri, 11 Jun 2021 02:46:39 +0100
+
udpkg (1.19) unstable; urgency=medium
* Team upload.
@@ -374,7 +390,7 @@
udpkg (0.004) unstable; urgency=low
- * fixes builddeps (closes: #86934)
+ * fixes builddeps (closes: #86934)
-- Randolph Chung <tausq@debian.org> Wed, 21 Feb 2001 21:00:45 -0700
@@ -397,5 +413,3 @@
* Non-release.
-- Joey Hess <joeyh@debian.org> Thu, 26 Oct 2000 12:02:04 -0700
-
-
diff -Nru udpkg-1.19/debian/control udpkg-1.20/debian/control
--- udpkg-1.19/debian/control 2018-08-10 20:25:18.000000000 +0100
+++ udpkg-1.20/debian/control 2021-06-10 23:04:38.000000000 +0100
@@ -2,7 +2,7 @@
Section: debian-installer
Priority: standard
Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
-Uploaders: Bastian Blank <waldi@debian.org>, Christian Perrier <bubulle@debian.org>
+Uploaders: Bastian Blank <waldi@debian.org>, Steve McIntyre <93sam@debian.org>
Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.7.0), libdebian-installer4-dev (>= 0.41), dh-autoreconf
Vcs-Browser: https://salsa.debian.org/installer-team/udpkg
Vcs-Git: https://salsa.debian.org/installer-team/udpkg.git
diff -Nru udpkg-1.19/status.c udpkg-1.20/status.c
--- udpkg-1.19/status.c 2018-08-10 20:25:18.000000000 +0100
+++ udpkg-1.20/status.c 2021-06-11 00:45:35.000000000 +0100
@@ -1,9 +1,11 @@
#include "udpkg.h"
+#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <search.h>
+#include <sys/file.h>
#include <debian-installer.h>
/* Status file handling routines
@@ -19,8 +21,15 @@
* control info from (new) packages is merged into the status file,
* replacing any pre-existing entries. when a merge happens, status info
* read using the status_read function is written back to the status file
+ *
+ * There is also a pair of functions to lock and unlock access to the
+ * status, to protect against multiple invocations of udpkg racing
+ * against each other. Callers are responsible for using this locking
+ * around any code that works with the status file.
*/
+static int lock_fd = -1;
+
static const char *statuswords[][10] = {
{ (char *)STATUS_WANTSTART, "unknown", "install", "hold",
"deinstall", "purge", 0 },
@@ -208,6 +217,45 @@
}
}
+void status_lock(void)
+{
+ int error;
+ lock_fd = open(STATUSFILELOCK, O_WRONLY | O_CREAT, 0200);
+ if (lock_fd < 0)
+ {
+ fprintf(stderr, "Unable to open lockfile %s (%d), abort!",
+ STATUSFILELOCK, errno);
+ exit(1);
+ }
+ error = flock(lock_fd, LOCK_EX);
+ if (error < 0)
+ {
+ fprintf(stderr, "Unable to lock lockfile %s (%d), abort!",
+ STATUSFILELOCK, errno);
+ exit(1);
+ }
+}
+
+void status_unlock(void)
+{
+ int error;
+ if (lock_fd < 0)
+ {
+ fprintf(stderr, "Trying to unlock when we don't have the lockfile %s open!",
+ STATUSFILELOCK);
+ exit(1);
+ }
+ error = flock(lock_fd, LOCK_UN);
+ if (error < 0)
+ {
+ fprintf(stderr, "Unable to unlock lockfile %s (%d), abort!",
+ STATUSFILELOCK, errno);
+ exit(1);
+ }
+ close(lock_fd);
+ lock_fd = -1;
+}
+
void *status_read(void)
{
FILE *f;
diff -Nru udpkg-1.19/udpkg.c udpkg-1.20/udpkg.c
--- udpkg-1.19/udpkg.c 2018-08-10 20:25:18.000000000 +0100
+++ udpkg-1.20/udpkg.c 2021-06-11 02:17:34.000000000 +0100
@@ -15,6 +15,14 @@
#include <sys/utsname.h>
#include <debian-installer.h>
+#ifdef LOCK_DEBUG
+# define STATUS_LOCK() fprintf(stderr, "%d(%d): trying to lock status file\n", getpid(),__LINE__); status_lock(); fprintf(stderr, "%d(%d): locked\n", getpid(),__LINE__)
+# define STATUS_UNLOCK() fprintf(stderr, "%d(%d): trying to unlock status file\n", getpid(),__LINE__); status_unlock(); fprintf(stderr, "%d(%d): unlocked\n", getpid(),__LINE__)
+#else
+# define STATUS_LOCK() status_lock()
+# define STATUS_UNLOCK() status_unlock()
+#endif
+
static int force_configure = 0;
static int loadtemplate = 1;
@@ -450,12 +458,14 @@
{
int r = 0;
struct package_t *pkg;
+ STATUS_LOCK();
void *status = status_read();
if (di_exec_shell_log("rm -rf -- " DPKGCIDIR) != 0 ||
mkdir(DPKGCIDIR, S_IRWXU) != 0)
{
perror("mkdir");
+ STATUS_UNLOCK();
return 1;
}
@@ -468,6 +478,7 @@
status_merge(status, pkgs);
if (di_exec_shell_log("rm -rf -- " DPKGCIDIR) != 0)
r = 1;
+ STATUS_UNLOCK();
return r;
}
@@ -476,7 +487,9 @@
int r = 0;
void *found;
struct package_t *pkg;
+ STATUS_LOCK();
void *status = status_read();
+ STATUS_UNLOCK();
for (pkg = pkgs; pkg != 0 && r == 0; pkg = pkg->next)
{
found = tfind(pkg, &status, package_compare);
@@ -492,18 +505,22 @@
r = dpkg_doconfigure(*(struct package_t **)found);
}
}
+ STATUS_LOCK();
status_merge(status, 0);
+ STATUS_UNLOCK();
return r;
}
static int dpkg_install(struct package_t *pkgs)
{
struct package_t *p, *ordered = 0;
+ STATUS_LOCK();
void *status = status_read();
if (di_exec_shell_log("rm -rf -- " DPKGCIDIR) != 0 ||
mkdir(DPKGCIDIR, S_IRWXU) != 0)
{
perror("mkdir");
+ STATUS_UNLOCK();
return 1;
}
@@ -542,6 +559,7 @@
if (ordered != 0)
status_merge(status, pkgs);
+ STATUS_UNLOCK();
return di_exec_shell_log("rm -rf -- " DPKGCIDIR);
}
@@ -602,6 +620,7 @@
struct package_t *p;
char buf[1024], buf2[1024];
FILE *fp;
+ STATUS_LOCK();
void *status = status_read();
for (p = pkgs; p != 0; p = p->next)
@@ -650,6 +669,7 @@
p->status |= STATUS_STATUSHALFINSTALLED;
}
status_merge(status, pkgs);
+ STATUS_UNLOCK();
return r;
#else
FPRINTF(stderr, "udpkg: No support for -r.\n");
diff -Nru udpkg-1.19/udpkg.h udpkg-1.20/udpkg.h
--- udpkg-1.19/udpkg.h 2018-08-10 20:25:18.000000000 +0100
+++ udpkg-1.20/udpkg.h 2021-06-10 01:19:44.000000000 +0100
@@ -19,6 +19,7 @@
#define BUFSIZE 4096
#define STATUSFILE ADMINDIR "/status"
+#define STATUSFILELOCK ADMINDIR "/status.lck"
#define DPKGCIDIR ADMINDIR "/tmp.ci/"
#define INFODIR ADMINDIR "/info/"
#define UDPKG_QUIET "UDPKG_QUIET"
@@ -95,6 +96,8 @@
void *status_read(void);
void control_read(FILE *f, struct package_t *p);
int status_merge(void *status, struct package_t *pkgs);
+void status_lock(void);
+void status_unlock(void);
int package_compare(const void *p1, const void *p2);
struct package_t *depends_resolve(struct package_t *pkgs, void *status);
Reply to: