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@xxxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html