Subject: [PATCH] builtin/fetch.c: clean tmp pack after receive signal

From: "SURA via GitGitGadget" <[email-masked]>
Date: Tue, 16 Mar 2021 02:53:36 +0000

From: SURA <[email-masked]>

In Gitee.com, I often use scripts to start a time-limited
"git fetch". When the execution time of'git fetch' is too
long, send a signal (such as SIGINT) to the'git fetch' process

But I found that after the process exits, there are some
files in the format of 'objects/pack/tmp_pack_XXXXXX' on the disk.
They are usually very large (some of them exceed 5G), and'git gc'
has no effect on them.

These fetch_tmp_pack files will gradually fill up the disk.
For a long time, I set F_WRLCK to the file to confirm whether the
file is opened by other processes, and delete the file if it is not opened

Obviously this is only a temporary solution, I think it should be fixed from git

I found fetch will start a 'index-pack' sub-process, this sub-process
create the tmp_pack
  1. make 'index-pack' unlink tmp_pack when get signal
  2. make 'fetch' send signal to 'index-pack' when get signal

Signed-off-by: SURA <[email-masked]>
---
    builtin/fetch.c: clean tmp pack after receive signal
    
    Clean tmp-pack after 'git fetch' process get signal(SIGINT, SIGHUP,
    SIGTERM, SIGQUIT or SIGPIPE)
    
    Only for operations using ‘wire protocol version 2’ and ssh
    
    Signed-off-by: SURA [email-masked]

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-890%2FSURA907%2Fgit-fetch-tmp-pack-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-890/SURA907/git-fetch-tmp-pack-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/890

 builtin/fetch-pack.c |  3 ++-
 builtin/fetch.c      | 10 ++++++++++
 builtin/index-pack.c | 18 ++++++++++++++++++
 fetch-pack.c         |  7 +++++--
 fetch-pack.h         |  3 ++-
 transport.c          |  3 ++-
 transport.h          |  6 ++++++
 7 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index c2d96f4c89ab..49a3e0bf2ae3 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -56,6 +56,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 	struct string_list deepen_not = STRING_LIST_INIT_DUP;
 	struct packet_reader reader;
 	enum protocol_version version;
+	pid_t index_pack_pid = -1;
 
 	fetch_if_missing = 0;
 
@@ -232,7 +233,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 	}
 
 	ref = fetch_pack(&args, fd, ref, sought, nr_sought,
-			 &shallow, pack_lockfiles_ptr, version);
+			 &shallow, pack_lockfiles_ptr, version, &index_pack_pid);
 	if (pack_lockfiles.nr) {
 		int i;
 
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 0b90de87c7a2..a87efa23ceb5 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -224,8 +224,18 @@ static void unlock_pack(void)
 		transport_unlock_pack(gsecondary);
 }
 
+static void send_signo_to_index_pack(int signo)
+{
+	if (gtransport && gtransport->index_pack_pid > 0)
+		kill(gtransport->index_pack_pid, signo);
+
+	if (gsecondary && gsecondary->index_pack_pid > 0)
+		kill(gsecondary->index_pack_pid, signo);
+}
+
 static void unlock_pack_on_signal(int signo)
 {
+	send_signo_to_index_pack(signo);
 	unlock_pack();
 	sigchain_pop(signo);
 	raise(signo);
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index bad57488079c..27d1ebba746e 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -15,10 +15,13 @@
 #include "packfile.h"
 #include "object-store.h"
 #include "promisor-remote.h"
+#include "sigchain.h"
 
 static const char index_pack_usage[] =
 "git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
 
+static const char *tmp_pack_name;
+
 struct object_entry {
 	struct pack_idx_entry idx;
 	unsigned long size;
@@ -336,6 +339,7 @@ static const char *open_pack_file(const char *pack_name)
 			output_fd = odb_mkstemp(&tmp_file,
 						"pack/tmp_pack_XXXXXX");
 			pack_name = strbuf_detach(&tmp_file, NULL);
+			tmp_pack_name = pack_name;
 		} else {
 			output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
 			if (output_fd < 0)
@@ -353,6 +357,19 @@ static const char *open_pack_file(const char *pack_name)
 	return pack_name;
 }
 
+static void remove_tmp_pack(void)
+{
+	if (tmp_pack_name) 
+		unlink_or_warn(tmp_pack_name);
+}
+
+static void remove_tmp_pack_on_signal(int signo)
+{
+	remove_tmp_pack();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
 static void parse_pack_header(void)
 {
 	struct pack_header *hdr = fill(sizeof(struct pack_header));
@@ -1911,6 +1928,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
 	}
 
 	curr_pack = open_pack_file(pack_name);
+	sigchain_push_common(remove_tmp_pack_on_signal);
 	parse_pack_header();
 	objects = xcalloc(st_add(nr_objects, 1), sizeof(struct object_entry));
 	if (show_stat)
diff --git a/fetch-pack.c b/fetch-pack.c
index 6a61a464283e..bedbf69710f6 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -40,6 +40,7 @@ static struct shallow_lock shallow_lock;
 static const char *alternate_shallow_file;
 static struct strbuf fsck_msg_types = STRBUF_INIT;
 static struct string_list uri_protocols = STRING_LIST_INIT_DUP;
+static pid_t *curr_index_pack_pid;
 
 /* Remember to update object flag allocation in object.h */
 #define COMPLETE	(1U << 0)
@@ -944,6 +945,7 @@ static int get_pack(struct fetch_pack_args *args,
 	cmd.git_cmd = 1;
 	if (start_command(&cmd))
 		die(_("fetch-pack: unable to fork off %s"), cmd_name);
+	*curr_index_pack_pid = cmd.pid;
 	if (do_keep && (pack_lockfiles || fsck_objects)) {
 		int is_well_formed;
 		char *pack_lockfile = index_pack_lockfile(cmd.out, &is_well_formed);
@@ -1945,12 +1947,13 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
 		       struct ref **sought, int nr_sought,
 		       struct oid_array *shallow,
 		       struct string_list *pack_lockfiles,
-		       enum protocol_version version)
+		       enum protocol_version version,
+		       pid_t *index_pack_pid)
 {
 	struct ref *ref_cpy;
 	struct shallow_info si;
 	struct oid_array shallows_scratch = OID_ARRAY_INIT;
-
+	curr_index_pack_pid = index_pack_pid;
 	fetch_pack_setup();
 	if (nr_sought)
 		nr_sought = remove_duplicates_in_refs(sought, nr_sought);
diff --git a/fetch-pack.h b/fetch-pack.h
index 736a3dae467a..c05a2544bb06 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -78,7 +78,8 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
 		       int nr_sought,
 		       struct oid_array *shallow,
 		       struct string_list *pack_lockfiles,
-		       enum protocol_version version);
+		       enum protocol_version version,
+			   pid_t *index_pack_pid);
 
 /*
  * Print an appropriate error message for each sought ref that wasn't
diff --git a/transport.c b/transport.c
index b13fab5dc3b1..b18f62e6bd23 100644
--- a/transport.c
+++ b/transport.c
@@ -391,7 +391,7 @@ static int fetch_refs_via_pack(struct transport *transport,
 	refs = fetch_pack(&args, data->fd,
 			  refs_tmp ? refs_tmp : transport->remote_refs,
 			  to_fetch, nr_heads, &data->shallow,
-			  &transport->pack_lockfiles, data->version);
+			  &transport->pack_lockfiles, data->version, &transport->index_pack_pid);
 
 	close(data->fd[0]);
 	close(data->fd[1]);
@@ -1095,6 +1095,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
 	}
 
 	ret->hash_algo = &hash_algos[GIT_HASH_SHA1];
+	ret->index_pack_pid = -1;
 
 	return ret;
 }
diff --git a/transport.h b/transport.h
index 24e15799e714..d25d76125784 100644
--- a/transport.h
+++ b/transport.h
@@ -118,6 +118,12 @@ struct transport {
 	enum transport_family family;
 
 	const struct git_hash_algo *hash_algo;
+
+	/*
+	 * Record the pid of the index_pack sub-process
+	 * used to send the signal to this sub-process after the main fetch process receives the signal
+	 */
+	pid_t index_pack_pid;
 };
 
 #define TRANSPORT_PUSH_ALL			(1<<0)

base-commit: 13d7ab6b5d7929825b626f050b62a11241ea4945
-- 
gitgitgadget