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

[PATCH v5] gc: save log from daemonized gc --auto and print it next time

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Sep 19, 2015, 05:13 UTC
Message-ID
<1442639603-25568-1-git-send-email-pclouds@gmail.com>
In-Reply-To
<1442108202-25746-1-git-send-email-pclouds@gmail.com>

While commit 9f673f9 (gc: config option for running --auto in background - 2014-02-08) helps reduce some complaints about 'gc --auto' hogging the terminal, it creates another set of problems.

The latest in this set is, as the result of daemonizing, stderr is closed and all warnings are lost. This warning at the end of cmd_gc() is particularly important because it tells the user how to avoid "gc --auto" running repeatedly. Because stderr is closed, the user does not know, naturally they complain about 'gc --auto' wasting CPU.

Daemonized gc now saves stderr to $GIT_DIR/gc.log. Following gc --auto will not run and gc.log printed out until the user removes gc.log.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 This is the lock-based version. I'm sending an alternative that does
 not need atexit() with comparison between the two.
 builtin/gc.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)
diff --git a/builtin/gc.c b/builtin/gc.c
index bcc75d9..4e738fa 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -43,6 +43,7 @@ static struct argv_array prune_worktrees = ARGV_ARRAY_INIT;
 static struct argv_array rerere = ARGV_ARRAY_INIT;
 
 static char *pidfile;
+static struct lock_file log_lock;
 
 static void remove_pidfile(void)
 {
@@ -57,6 +58,28 @@ static void remove_pidfile_on_signal(int signo)
 	raise(signo);
 }
 
+static void process_log_file(void)
+{
+	struct stat st;
+	if (!fstat(log_lock.fd, &st) && st.st_size)
+		commit_lock_file(&log_lock);
+	else
+		rollback_lock_file(&log_lock);
+}
+
+static void process_log_file_at_exit(void)
+{
+	fflush(stderr);
+	process_log_file();
+}
+
+static void process_log_file_on_signal(int signo)
+{
+	process_log_file();
+	sigchain_pop(signo);
+	raise(signo);
+}
+
 static void git_config_date_string(const char *key, const char **output)
 {
 	if (git_config_get_string_const(key, output))
@@ -253,6 +276,24 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
 	return NULL;
 }
 
+static int report_last_gc_error(void)
+{
+	struct strbuf sb = STRBUF_INIT;
+	int ret;
+
+	ret = strbuf_read_file(&sb, git_path("gc.log"), 0);
+	if (ret > 0)
+		return error(_("The last gc run reported the following. "
+			       "Please correct the root cause\n"
+			       "and remove %s.\n"
+			       "Automatic cleanup will not be performed "
+			       "until the file is removed.\n\n"
+			       "%s"),
+			     git_path("gc.log"), sb.buf);
+	strbuf_release(&sb);
+	return 0;
+}
+
 static int gc_before_repack(void)
 {
 	if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
@@ -274,6 +315,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 	int force = 0;
 	const char *name;
 	pid_t pid;
+	int daemonized = 0;
 
 	struct option builtin_gc_options[] = {
 		OPT__QUIET(&quiet, N_("suppress progress reporting")),
@@ -330,13 +372,16 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 			fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
 		}
 		if (detach_auto) {
+			if (report_last_gc_error())
+				return -1;
+
 			if (gc_before_repack())
 				return -1;
 			/*
 			 * failure to daemonize is ok, we'll continue
 			 * in foreground
 			 */
-			daemonize();
+			daemonized = !daemonize();
 		}
 	} else
 		add_repack_all_option();
@@ -349,6 +394,15 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
 		    name, (uintmax_t)pid);
 	}
 
+	if (daemonized) {
+		hold_lock_file_for_update(&log_lock,
+					  git_path("gc.log"),
+					  LOCK_DIE_ON_ERROR);
+		dup2(log_lock.fd, 2);
+		sigchain_push_common(process_log_file_on_signal);
+		atexit(process_log_file_at_exit);
+	}
+
 	if (gc_before_repack())
 		return -1;
 
-- 
2.3.0.rc1.137.g477eb31
Previous: Junio C HamanoNext: Junio C Hamano
Message 14 of 17 in “Since gc.autodetach=1 you can end up with auto-gc on every command with no user notification”
  1. Ævar Arnfjörð BjarmasonJul 8, 2015
  2. Duy NguyenJul 8, 2015
  3. gc: save log from daemonized gc --auto and print it next timeNguyễn Thái Ngọc Duy, Aug 22, 2015
  4. Junio C HamanoAug 25, 2015
  5. Duy NguyenAug 31, 2015
  6. gc: save log from daemonized gc --auto and print it next timeNguyễn Thái Ngọc Duy, Sep 13, 2015
  7. Junio C HamanoSep 14, 2015
  8. Junio C HamanoSep 14, 2015
  9. Michael HaggertySep 16, 2015
  10. Junio C HamanoSep 16, 2015
  11. Michael HaggertySep 17, 2015
  12. Duy NguyenSep 17, 2015
  13. Junio C HamanoSep 17, 2015
  14. gc: save log from daemonized gc --auto and print it next timeNguyễn Thái Ngọc Duy, Sep 19, 2015
  15. Junio C HamanoSep 21, 2015
  16. gc: save log from daemonized gc --auto and print it next timeNguyễn Thái Ngọc Duy, Sep 19, 2015
  17. Junio C HamanoSep 21, 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.