[pacman-dev] [PATCH] alpm_handle: store lock file descriptor

Andrew Gregory andrew.gregory.8 at gmail.com
Fri Oct 25 09:59:17 EDT 2013


There is a brief window between opening the file descriptor and creating
a stream to it.  If the process was interrupted during that window the
lock file will not be removed correctly.  Tracking the file descriptor
allows us to remove the lock file regardless of whether or not the
stream was ever created.

Fixes FS#35603

Signed-off-by: Andrew Gregory <andrew.gregory.8 at gmail.com>
---
 lib/libalpm/handle.c | 29 +++++++++++++++++------------
 lib/libalpm/handle.h |  1 +
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/lib/libalpm/handle.c b/lib/libalpm/handle.c
index 53c86c5..c9a70c9 100644
--- a/lib/libalpm/handle.c
+++ b/lib/libalpm/handle.c
@@ -91,11 +91,10 @@ void _alpm_handle_free(alpm_handle_t *handle)
 /** Lock the database */
 int _alpm_handle_lock(alpm_handle_t *handle)
 {
-	int fd;
 	char *dir, *ptr;
 
 	ASSERT(handle->lockfile != NULL, return -1);
-	ASSERT(handle->lckstream == NULL, return 0);
+	ASSERT(handle->lockfd < 0, return 0);
 
 	/* create the dir of the lockfile first */
 	dir = strdup(handle->lockfile);
@@ -110,14 +109,13 @@ int _alpm_handle_lock(alpm_handle_t *handle)
 	FREE(dir);
 
 	do {
-		fd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000);
-	} while(fd == -1 && errno == EINTR);
-	if(fd >= 0) {
-		FILE *f = fdopen(fd, "w");
-		fprintf(f, "%ld\n", (long)getpid());
-		fflush(f);
-		fsync(fd);
-		handle->lckstream = f;
+		handle->lockfd = open(handle->lockfile, O_WRONLY | O_CREAT | O_EXCL, 0000);
+	} while(handle->lockfd == -1 && errno == EINTR);
+	if(handle->lockfd >= 0) {
+		handle->lckstream = fdopen(handle->lockfd, "w");
+		fprintf(handle->lckstream, "%ld\n", (long)getpid());
+		fflush(handle->lckstream);
+		fsync(handle->lockfd);
 		return 0;
 	}
 	return -1;
@@ -127,10 +125,17 @@ int _alpm_handle_lock(alpm_handle_t *handle)
 int _alpm_handle_unlock(alpm_handle_t *handle)
 {
 	ASSERT(handle->lockfile != NULL, return -1);
-	ASSERT(handle->lckstream != NULL, return 0);
+	ASSERT(handle->lockfd >= 0, return 0);
+
+	if(handle->lckstream) {
+		fclose(handle->lckstream);
+	} else {
+		/* no stream was opened, close the file descriptor directly */
+		close(handle->lockfd);
+	}
 
-	fclose(handle->lckstream);
 	handle->lckstream = NULL;
+	handle->lockfd = -1;
 
 	if(unlink(handle->lockfile) && errno != ENOENT) {
 		return -1;
diff --git a/lib/libalpm/handle.h b/lib/libalpm/handle.h
index 5e84d58..0395db9 100644
--- a/lib/libalpm/handle.h
+++ b/lib/libalpm/handle.h
@@ -55,6 +55,7 @@ struct __alpm_handle_t {
 	alpm_db_t *db_local;       /* local db pointer */
 	alpm_list_t *dbs_sync;  /* List of (alpm_db_t *) */
 	FILE *logstream;        /* log file stream pointer */
+	int lockfd;             /* lock file descriptor */
 	FILE *lckstream;        /* lock file stream pointer if one exists */
 	alpm_trans_t *trans;
 
-- 
1.8.4.1



More information about the pacman-dev mailing list