gc: save log from daemonized gc --auto and print it next time
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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
ecad27cf98
commit
329e6e8794
56
builtin/gc.c
56
builtin/gc.c
@ -41,6 +41,7 @@ static struct argv_array prune = ARGV_ARRAY_INIT;
|
|||||||
static struct argv_array rerere = ARGV_ARRAY_INIT;
|
static struct argv_array rerere = ARGV_ARRAY_INIT;
|
||||||
|
|
||||||
static char *pidfile;
|
static char *pidfile;
|
||||||
|
static struct lock_file log_lock;
|
||||||
|
|
||||||
static void remove_pidfile(void)
|
static void remove_pidfile(void)
|
||||||
{
|
{
|
||||||
@ -55,6 +56,28 @@ static void remove_pidfile_on_signal(int signo)
|
|||||||
raise(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 gc_config(void)
|
static void gc_config(void)
|
||||||
{
|
{
|
||||||
const char *value;
|
const char *value;
|
||||||
@ -248,6 +271,24 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
|
|||||||
return NULL;
|
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)
|
static int gc_before_repack(void)
|
||||||
{
|
{
|
||||||
if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
|
if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
|
||||||
@ -269,6 +310,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
|||||||
int force = 0;
|
int force = 0;
|
||||||
const char *name;
|
const char *name;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int daemonized = 0;
|
||||||
|
|
||||||
struct option builtin_gc_options[] = {
|
struct option builtin_gc_options[] = {
|
||||||
OPT__QUIET(&quiet, N_("suppress progress reporting")),
|
OPT__QUIET(&quiet, N_("suppress progress reporting")),
|
||||||
@ -324,13 +366,16 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
|||||||
fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
|
fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
|
||||||
}
|
}
|
||||||
if (detach_auto) {
|
if (detach_auto) {
|
||||||
|
if (report_last_gc_error())
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (gc_before_repack())
|
if (gc_before_repack())
|
||||||
return -1;
|
return -1;
|
||||||
/*
|
/*
|
||||||
* failure to daemonize is ok, we'll continue
|
* failure to daemonize is ok, we'll continue
|
||||||
* in foreground
|
* in foreground
|
||||||
*/
|
*/
|
||||||
daemonize();
|
daemonized = !daemonize();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
add_repack_all_option();
|
add_repack_all_option();
|
||||||
@ -343,6 +388,15 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
|
|||||||
name, (uintmax_t)pid);
|
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())
|
if (gc_before_repack())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user