{"thread":{"id":"1106","subject":"[PATCH] Unlock refs files on error exit","startedAt":"2005-07-04T20:08:55Z","lastAt":"2005-07-04T20:08:55Z","messageCount":1,"participants":["Daniel Barkalow"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"5641","messageId":"Pine.LNX.4.21.0507041557310.30848-100000@iabervon.org","threadId":"1106","inReplyTo":null,"subject":"[PATCH] Unlock refs files on error exit","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2005-07-04T20:08:55Z","receivedAt":"2005-07-04T20:08:55Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"If a program locks a refs file (as git-ssh-pull -w now does for an\nexisting file), it should unlock it again if it exits without changing\nit. Some trickiness is required to make this not happen in forks of the\nprocess.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\n\n---\ncommit 8934c88118c900fe38abbf60f893ee9ef4e83b3c\ntree 62a74516551505e5fd2b5c2fd14486f3ac8a400e\nparent 2045e6098dfa0f8760b6a4a65227a6ea51de990d\nauthor Daniel Barkalow <barkalow@iabervon.org> 1120507109 -0400\ncommitter Daniel Barkalow <barkalow@silva-tulga.(none)> 1120507109 -0400\n\nIndex: refs.c\n===================================================================\n--- 3d3e671c0ac57ea66434768c2b3432352b7c20ae/refs.c  (mode:100644 sha1:447080edde385a470a815944c2f002c1e51699a5)\n+++ 62a74516551505e5fd2b5c2fd14486f3ac8a400e/refs.c  (mode:100644 sha1:6e75e82665f5c8e3e155579228c5104c16318239)\n@@ -2,6 +2,14 @@\n #include \"cache.h\"\n \n #include <errno.h>\n+#include <signal.h>\n+\n+#define MAX_LOCKS 10\n+\n+static int setup = 0;\n+\n+static int num_locks = 0;\n+static char *locknames[MAX_LOCKS];\n \n static int read_ref(const char *path, unsigned char *sha1)\n {\n@@ -88,6 +96,22 @@\n \treturn ret;\n }\n \n+static void remove_lock_files(void)\n+{\n+\tint i;\n+\tif (getpid() != setup)\n+\t\treturn;\n+\tfor (i = 0; i < num_locks; i++) {\n+\t\tunlink(locknames[i]);\n+\t}\n+\tnum_locks = 0;\n+}\n+\n+static void remove_lock_files_on_signal(int signo) \n+{\n+\tremove_lock_files();\n+}\n+\n static int read_ref_file(const char *filename, unsigned char *sha1) {\n \tint fd = open(filename, O_RDONLY);\n \tchar hex[41];\n@@ -120,9 +144,12 @@\n static int lock_ref_file(const char *filename, const char *lock_filename,\n \t\t\t const unsigned char *old_sha1)\n {\n-\tint fd = open(lock_filename, O_WRONLY | O_CREAT | O_EXCL, 0666);\n+\tint fd;\n \tunsigned char current_sha1[20];\n \tint retval;\n+\tif (num_locks >= MAX_LOCKS)\n+\t\treturn error(\"Too many locks in refs.c\");\n+\tfd = open(lock_filename, O_WRONLY | O_CREAT | O_EXCL, 0666);\n \tif (fd < 0) {\n \t\treturn error(\"Couldn't open lock file for %s: %s\",\n \t\t\t     filename, strerror(errno));\n@@ -151,6 +178,12 @@\n \t\t\t\t     sha1_to_hex(current_sha1), filename);\n \t\t}\n \t}\n+\tif (!setup) {\n+\t\tsignal(SIGINT, remove_lock_files_on_signal);\n+\t\tatexit(remove_lock_files);\n+\t\tsetup = getpid();\n+\t}\n+\tlocknames[num_locks++] = strdup(lock_filename);\n \treturn fd;\n }\n \n@@ -175,6 +208,7 @@\n {\n \tchar *hex = sha1_to_hex(sha1);\n \tchar term = '\\n';\n+\tint i;\n \tif (write(fd, hex, 40) < 40 ||\n \t    write(fd, &term, 1) < 1) {\n \t\terror(\"Couldn't write %s\\n\", filename);\n@@ -182,7 +216,14 @@\n \t\treturn -1;\n \t}\n \tclose(fd);\n-\trename(lock_filename, filename);\n+\tif (rename(lock_filename, filename))\n+\t\treturn error(\"Couldn't update %s\", filename);\n+\tfor (i = 0; i < num_locks; i++) {\n+\t\tif (!strcmp(lock_filename, locknames[i])) {\n+\t\t\tlocknames[i] = locknames[--num_locks];\n+\t\t\tbreak;\n+\t\t}\n+\t}\n \treturn 0;\n }\n \n"}]}