[pacman-dev] [PATCH 1/1] alpm: use flock() for db lock

Christian Hesse list at eworm.de
Tue Jun 6 21:26:28 UTC 2017


From: Christian Hesse <mail at eworm.de>

We used to check for file existens, but that suffers from stale lock
files caused by unexpected events like crash, shutdown, etc.

Instead use flock() to lock the file. It does not matter whether or
not the file exists but whether an exclusive lock can be obtained.

Also remove the hint about removing the file from pacman.

Signed-off-by: Christian Hesse <mail at eworm.de>
---
 lib/libalpm/handle.c | 17 +++++++++++++++--
 src/pacman/util.c    |  5 -----
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index b6b27881..bb5cc907 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
+#include <sys/file.h>
 #include <sys/types.h>
 #include <syslog.h>
 #include <sys/stat.h>
@@ -120,10 +121,20 @@ int _alpm_handle_lock(alpm_handle_t *handle)
 	FREE(dir);
 
 	do {
-		handle->lockfd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
+		handle->lockfd = open(handle->lockfile, O_WRONLY | O_CREAT | O_CLOEXEC, 0000);
 	} while(handle->lockfd == -1 && errno == EINTR);
 
-	return (handle->lockfd >= 0 ? 0 : -1);
+	if (handle->lockfd == -1)
+		return -1;
+
+	/* try to get an exclusive lock */
+	if (flock(handle->lockfd, LOCK_EX | LOCK_NB) == -1) {
+		close(handle->lockfd);
+		handle->lockfd = -1;
+		return -1;
+	}
+
+	return 0;
 }
 
 /** Remove the database lock file
@@ -137,6 +148,8 @@ int SYMEXPORT alpm_unlock(alpm_handle_t *handle)
 	ASSERT(handle->lockfile != NULL, return 0);
 	ASSERT(handle->lockfd >= 0, return 0);
 
+	flock(handle->lockfd, LOCK_UN);
+
 	close(handle->lockfd);
 	handle->lockfd = -1;
 
diff --git a/src/pacman/util.c b/src/pacman/util.c
index ae8a74d3..c3f9d3ba 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -81,13 +81,8 @@ void trans_init_error(void)
 	pm_printf(ALPM_LOG_ERROR, _("failed to init transaction (%s)\n"),
 			alpm_strerror(err));
 	if(err == ALPM_ERR_HANDLE_LOCK) {
-		const char *lockfile = alpm_option_get_lockfile(config->handle);
 		pm_printf(ALPM_LOG_ERROR, _("could not lock database: %s\n"),
 					strerror(errno));
-		if(access(lockfile, F_OK) == 0) {
-			fprintf(stderr, _("  if you're sure a package manager is not already\n"
-						"  running, you can remove %s\n"), lockfile);
-		}
 	}
 }
 
-- 
2.13.1


More information about the pacman-dev mailing list