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

[PATCH/RFC 1/2] sha1_file: close all pack files after running

From
Max Kirillov <max@max630.net>
Date
Oct 1, 2015, 03:29 UTC
Message-ID
<1443670163-31193-2-git-send-email-max@max630.net>
In-Reply-To
<1443670163-31193-1-git-send-email-max@max630.net>

When a builtin has done its job, but waits for pager or not waited by its caller and still hanging it keeps pack files opened. This can cause a number of issues, for example on Windows git gc cannot remove the packs.

Fix this by explicitly closing all pack files and unmapping memory from the packs after running builtin. Do not die() if the memory region is still used though, just print a warning, because failure to close a file should not prevent the currently running program from finishing its task.

Signed-off-by: Max Kirillov <max@max630.net>
---
 cache.h     |  1 +
 git.c       |  2 ++
 sha1_file.c | 32 +++++++++++++++++++++++++++++---
 3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/cache.h b/cache.h
index 79066e5..153bc46 100644
--- a/cache.h
+++ b/cache.h
@@ -1279,6 +1279,7 @@ extern void unuse_pack(struct pack_window **);
 extern void free_pack_by_name(const char *);
 extern void clear_delta_base_cache(void);
 extern struct packed_git *add_packed_git(const char *, int, int);
+extern void close_all_packs(void);
 
 /*
  * Return the SHA-1 of the nth object within the specified packfile.
diff --git a/git.c b/git.c
index 5feba41..ad34680 100644
--- a/git.c
+++ b/git.c
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "cache.h"
 #include "exec_cmd.h"
 #include "help.h"
 #include "run-command.h"
@@ -348,6 +349,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
 	trace_argv_printf(argv, "trace: built-in: git");
 
 	status = p->fn(argc, argv, prefix);
+	close_all_packs();
 	if (status)
 		return status;
 
diff --git a/sha1_file.c b/sha1_file.c
index 08302f5..62f1dad 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -773,20 +773,28 @@ void *xmmap(void *start, size_t length,
 	return ret;
 }
 
-void close_pack_windows(struct packed_git *p)
+static int close_pack_windows_nodie(struct packed_git *p)
 {
 	while (p->windows) {
 		struct pack_window *w = p->windows;
 
 		if (w->inuse_cnt)
-			die("pack '%s' still has open windows to it",
-			    p->pack_name);
+			return 1;
+
 		munmap(w->base, w->len);
 		pack_mapped -= w->len;
 		pack_open_windows--;
 		p->windows = w->next;
 		free(w);
 	}
+
+	return 0;
+}
+
+void close_pack_windows(struct packed_git *p)
+{
+	if (close_pack_windows_nodie(p))
+		die("pack '%s' still has open windows to it", p->pack_name);
 }
 
 /*
@@ -866,6 +874,24 @@ static int close_one_pack(void)
 	return 0;
 }
 
+void close_all_packs(void)
+{
+	struct packed_git *p = NULL;
+
+	for (p = packed_git; p; p = p->next) {
+		if (close_pack_windows_nodie(p))
+			warning("pack '%s' still has open windows to it", p->pack_name);
+
+		if (p->pack_fd != -1) {
+			if (close(p->pack_fd) != 0)
+				warning("close(%s) failed: %d", p->pack_name, errno);
+			p->pack_fd = -1;
+		}
+
+		close_pack_index(p);
+	}
+}
+
 void unuse_pack(struct pack_window **w_cursor)
 {
 	struct pack_window *w = *w_cursor;
-- 
2.3.4.2801.g3d0809b
Previous: Max KirillovNext: Johannes Schindelin
Message 2 of 12 in “close packs files when they are not needed”
  1. 0/2 close packs files when they are not neededMax Kirillov, Oct 1, 2015
  2. 1/2 sha1_file: close all pack files after runningMax Kirillov, Oct 1, 2015
  3. Johannes SchindelinOct 2, 2015
  4. Johannes SchindelinOct 2, 2015
  5. Max KirillovOct 2, 2015
  6. Johannes SchindelinOct 4, 2015
  7. Max KirillovOct 5, 2015
  8. Johannes SchindelinOct 5, 2015
  9. Max KirillovOct 2, 2015
  10. Max KirillovOct 2, 2015
  11. 2/2 sha1_file: set packfile to O_CLOEXEC at openMax Kirillov, Oct 1, 2015
  12. Johannes SchindelinOct 2, 2015

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.