From: Andres Perera <andres.p@zoho.com>
To: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Cc: git@vger.kernel.org, Ramkumar Ramachandra <artagnon@gmail.com>,
Junio C Hamano <gitster@pobox.com>, Johannes Sixt <j6t@kdbg.org>
Subject: Re: [PATCH v4] gc: reject if another gc is running, unless --force is given
Date: Fri, 9 Aug 2013 11:59:39 -0430 [thread overview]
Message-ID: <CAPrKj1bO1jBsv73beA6LoeN09S-jWq8FYOP+WQ-AFwb1dn4Wsw@mail.gmail.com> (raw)
In-Reply-To: <1375959938-6395-1-git-send-email-pclouds@gmail.com>
On Thu, Aug 8, 2013 at 6:35 AM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:
> This may happen when `git gc --auto` is run automatically, then the
> user, to avoid wait time, switches to a new terminal, keeps working
> and `git gc --auto` is started again because the first gc instance has
> not clean up the repository.
>
> This patch tries to avoid multiple gc running, especially in --auto
> mode. In the worst case, gc may be delayed 12 hours if a daemon reuses
> the pid stored in gc.pid.
>
> kill(pid, 0) support is added to MinGW port so it should work on
> Windows too.
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
> this patch is getting cooler:
>
> - uname() is dropped in favor of gethostbyname(), which is supported
> by MinGW port.
> - host name is stored in gc.pid as junio suggested so...
> - now we can say "gc is already running on _this host_ with _this pid_..."
>
> Documentation/git-gc.txt | 6 ++++-
> builtin/gc.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++
> compat/mingw.c | 6 +++++
> 3 files changed, 78 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
> index 2402ed6..e158a3b 100644
> --- a/Documentation/git-gc.txt
> +++ b/Documentation/git-gc.txt
> @@ -9,7 +9,7 @@ git-gc - Cleanup unnecessary files and optimize the local repository
> SYNOPSIS
> --------
> [verse]
> -'git gc' [--aggressive] [--auto] [--quiet] [--prune=<date> | --no-prune]
> +'git gc' [--aggressive] [--auto] [--quiet] [--prune=<date> | --no-prune] [--force]
>
> DESCRIPTION
> -----------
> @@ -72,6 +72,10 @@ automatic consolidation of packs.
> --quiet::
> Suppress all progress reports.
>
> +--force::
> + Force `git gc` to run even if there may be another `git gc`
> + instance running on this repository.
> +
> Configuration
> -------------
>
> diff --git a/builtin/gc.c b/builtin/gc.c
> index 6be6c8d..99682f0 100644
> --- a/builtin/gc.c
> +++ b/builtin/gc.c
> @@ -167,11 +167,69 @@ static int need_to_gc(void)
> return 1;
> }
>
> +/* return NULL on success, else hostname running the gc */
> +static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
> +{
> + static struct lock_file lock;
> + static char locking_host[128];
> + char my_host[128];
> + struct strbuf sb = STRBUF_INIT;
> + struct stat st;
> + uintmax_t pid;
pid_t is always an signed type, therefore unintmax_t does not make
sense as a catch all value
fork() returns -1 on failure, and its return type is pid_t. i don't
know what fantasy unix system has an unsigned pid_t
> + FILE *fp;
> + int fd, should_exit;
> +
> + if (gethostname(my_host, sizeof(my_host)))
> + strcpy(my_host, "unknown");
> +
> + fd = hold_lock_file_for_update(&lock, git_path("gc.pid"),
> + LOCK_DIE_ON_ERROR);
> + if (!force) {
> + fp = fopen(git_path("gc.pid"), "r");
> + memset(locking_host, 0, sizeof(locking_host));
> + should_exit =
> + fp != NULL &&
> + !fstat(fileno(fp), &st) &&
> + /*
> + * 12 hour limit is very generous as gc should
> + * never take that long. On the other hand we
> + * don't really need a strict limit here,
> + * running gc --auto one day late is not a big
> + * problem. --force can be used in manual gc
> + * after the user verifies that no gc is
> + * running.
> + */
> + time(NULL) - st.st_mtime <= 12 * 3600 &&
> + fscanf(fp, "%"PRIuMAX" %127c", &pid, locking_host) == 2 &&
similar comment wrt PRIuMAX
> + !strcmp(locking_host, my_host) &&
> + !kill(pid, 0);
> + if (fp != NULL)
> + fclose(fp);
> + if (should_exit) {
> + if (fd >= 0)
> + rollback_lock_file(&lock);
> + *ret_pid = pid;
> + return locking_host;
why not exponential backoff?
> + }
> + }
> +
> + strbuf_addf(&sb, "%"PRIuMAX" %s",
> + (uintmax_t) getpid(), my_host);
> + write_in_full(fd, sb.buf, sb.len);
> + strbuf_release(&sb);
> + commit_lock_file(&lock);
> +
> + return NULL;
> +}
> +
> int cmd_gc(int argc, const char **argv, const char *prefix)
> {
> int aggressive = 0;
> int auto_gc = 0;
> int quiet = 0;
> + int force = 0;
> + const char *name;
> + pid_t pid;
>
> struct option builtin_gc_options[] = {
> OPT__QUIET(&quiet, N_("suppress progress reporting")),
> @@ -180,6 +238,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
> PARSE_OPT_OPTARG, NULL, (intptr_t)prune_expire },
> OPT_BOOLEAN(0, "aggressive", &aggressive, N_("be more thorough (increased runtime)")),
> OPT_BOOLEAN(0, "auto", &auto_gc, N_("enable auto-gc mode")),
> + OPT_BOOL(0, "force", &force, N_("force running gc even if there may be another gc running")),
> OPT_END()
> };
>
> @@ -225,6 +284,14 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
> } else
> add_repack_all_option();
>
> + name = lock_repo_for_gc(force, &pid);
> + if (name) {
> + if (auto_gc)
> + return 0; /* be quiet on --auto */
> + die(_("gc is already running on machine '%s' pid %"PRIuMAX" (use --force if not)"),
> + name, (uintmax_t)pid);
> + }
> +
> if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
> return error(FAILED_RUN, pack_refs_cmd.argv[0]);
>
> diff --git a/compat/mingw.c b/compat/mingw.c
> index bb92c43..22ee9ef 100644
> --- a/compat/mingw.c
> +++ b/compat/mingw.c
> @@ -1086,6 +1086,12 @@ int mingw_kill(pid_t pid, int sig)
> errno = err_win_to_posix(GetLastError());
> CloseHandle(h);
> return -1;
> + } else if (pid > 0 && sig == 0) {
> + HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
> + if (h) {
> + CloseHandle(h);
> + return 0;
> + }
> }
>
> errno = EINVAL;
> --
> 1.8.2.83.gc99314b
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
next prev parent reply other threads:[~2013-08-09 16:29 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-03 4:20 [PATCH] gc: reject if another gc is running, unless --force is given Nguyễn Thái Ngọc Duy
2013-08-03 6:21 ` [PATCH v2] " Nguyễn Thái Ngọc Duy
2013-08-03 7:52 ` Ramkumar Ramachandra
2013-08-03 10:01 ` Duy Nguyen
2013-08-03 9:49 ` Johannes Sixt
2013-08-03 10:01 ` Duy Nguyen
2013-08-03 10:40 ` Johannes Sixt
2013-08-05 14:19 ` [PATCH v3] " Nguyễn Thái Ngọc Duy
2013-08-05 18:17 ` Junio C Hamano
2013-08-05 18:37 ` Ramkumar Ramachandra
2013-08-06 6:43 ` Junio C Hamano
2013-08-06 6:45 ` Ramkumar Ramachandra
2013-08-08 11:05 ` [PATCH v4] " Nguyễn Thái Ngọc Duy
2013-08-08 18:12 ` Junio C Hamano
2013-08-09 12:52 ` Duy Nguyen
2013-08-09 16:00 ` Junio C Hamano
2013-08-09 16:29 ` Andres Perera [this message]
2013-08-09 17:41 ` Junio C Hamano
2013-08-10 0:45 ` Duy Nguyen
2013-08-10 7:11 ` Andreas Schwab
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAPrKj1bO1jBsv73beA6LoeN09S-jWq8FYOP+WQ-AFwb1dn4Wsw@mail.gmail.com \
--to=andres.p@zoho.com \
--cc=artagnon@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=j6t@kdbg.org \
--cc=pclouds@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).