git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Unlock refs files on error exit

From
Daniel Barkalow <barkalow@iabervon.org>
Date
Jul 4, 2005, 20:08 UTC
Message-ID
<Pine.LNX.4.21.0507041557310.30848-100000@iabervon.org>

If a program locks a refs file (as git-ssh-pull -w now does for an existing file), it should unlock it again if it exits without changing it. Some trickiness is required to make this not happen in forks of the process.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>

--- commit 8934c88118c900fe38abbf60f893ee9ef4e83b3c tree 62a74516551505e5fd2b5c2fd14486f3ac8a400e parent 2045e6098dfa0f8760b6a4a65227a6ea51de990d author Daniel Barkalow <barkalow@iabervon.org> 1120507109 -0400 committer Daniel Barkalow <barkalow@silva-tulga.(none)> 1120507109 -0400

Index: refs.c
===================================================================
--- 3d3e671c0ac57ea66434768c2b3432352b7c20ae/refs.c  (mode:100644 sha1:447080edde385a470a815944c2f002c1e51699a5)
+++ 62a74516551505e5fd2b5c2fd14486f3ac8a400e/refs.c  (mode:100644 sha1:6e75e82665f5c8e3e155579228c5104c16318239)
@@ -2,6 +2,14 @@
 #include "cache.h"
 
 #include <errno.h>
+#include <signal.h>
+
+#define MAX_LOCKS 10
+
+static int setup = 0;
+
+static int num_locks = 0;
+static char *locknames[MAX_LOCKS];
 
 static int read_ref(const char *path, unsigned char *sha1)
 {
@@ -88,6 +96,22 @@
 	return ret;
 }
 
+static void remove_lock_files(void)
+{
+	int i;
+	if (getpid() != setup)
+		return;
+	for (i = 0; i < num_locks; i++) {
+		unlink(locknames[i]);
+	}
+	num_locks = 0;
+}
+
+static void remove_lock_files_on_signal(int signo) 
+{
+	remove_lock_files();
+}
+
 static int read_ref_file(const char *filename, unsigned char *sha1) {
 	int fd = open(filename, O_RDONLY);
 	char hex[41];
@@ -120,9 +144,12 @@
 static int lock_ref_file(const char *filename, const char *lock_filename,
 			 const unsigned char *old_sha1)
 {
-	int fd = open(lock_filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
+	int fd;
 	unsigned char current_sha1[20];
 	int retval;
+	if (num_locks >= MAX_LOCKS)
+		return error("Too many locks in refs.c");
+	fd = open(lock_filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
 	if (fd < 0) {
 		return error("Couldn't open lock file for %s: %s",
 			     filename, strerror(errno));
@@ -151,6 +178,12 @@
 				     sha1_to_hex(current_sha1), filename);
 		}
 	}
+	if (!setup) {
+		signal(SIGINT, remove_lock_files_on_signal);
+		atexit(remove_lock_files);
+		setup = getpid();
+	}
+	locknames[num_locks++] = strdup(lock_filename);
 	return fd;
 }
 
@@ -175,6 +208,7 @@
 {
 	char *hex = sha1_to_hex(sha1);
 	char term = '\n';
+	int i;
 	if (write(fd, hex, 40) < 40 ||
 	    write(fd, &term, 1) < 1) {
 		error("Couldn't write %s\n", filename);
@@ -182,7 +216,14 @@
 		return -1;
 	}
 	close(fd);
-	rename(lock_filename, filename);
+	if (rename(lock_filename, filename))
+		return error("Couldn't update %s", filename);
+	for (i = 0; i < num_locks; i++) {
+		if (!strcmp(lock_filename, locknames[i])) {
+			locknames[i] = locknames[--num_locks];
+			break;
+		}
+	}
 	return 0;
 }
 
Message 1 of 1 in “Unlock refs files on error exit”
  1. Unlock refs files on error exitDaniel Barkalow, Jul 4, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.