[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: