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

Re: [PATCH v4] gc: reject if another gc is running, unless --force is given

From
APAndres Perera <andres.p@zoho.com>
Date
Aug 9, 2013, 16:29 UTC
Message-ID
<CAPrKj1bO1jBsv73beA6LoeN09S-jWq8FYOP+WQ-AFwb1dn4Wsw@mail.gmail.com>
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:
Show 67 quoted lines
> 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

Show 25 quoted lines
> +       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
Show 9 quoted lines
> +                       !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?
Show 71 quoted lines
> +               }
> +       }
> +
> +       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
>
Previous: Junio C HamanoNext: Junio C Hamano
Message 17 of 20 in “gc: reject if another gc is running, unless --force is given”
  1. gc: reject if another gc is running, unless --force is givenNguyễn Thái Ngọc Duy, Aug 3, 2013
  2. gc: reject if another gc is running, unless --force is givenNguyễn Thái Ngọc Duy, Aug 3, 2013
  3. Ramkumar RamachandraAug 3, 2013
  4. Duy NguyenAug 3, 2013
  5. Johannes SixtAug 3, 2013
  6. Duy NguyenAug 3, 2013
  7. Johannes SixtAug 3, 2013
  8. gc: reject if another gc is running, unless --force is givenNguyễn Thái Ngọc Duy, Aug 5, 2013
  9. Junio C HamanoAug 5, 2013
  10. Ramkumar RamachandraAug 5, 2013
  11. Junio C HamanoAug 6, 2013
  12. Ramkumar RamachandraAug 6, 2013
  13. gc: reject if another gc is running, unless --force is givenNguyễn Thái Ngọc Duy, Aug 8, 2013
  14. Junio C HamanoAug 8, 2013
  15. Duy NguyenAug 9, 2013
  16. Junio C HamanoAug 9, 2013
  17. Andres PereraAug 9, 2013
  18. Junio C HamanoAug 9, 2013
  19. Duy NguyenAug 10, 2013
  20. Andreas SchwabAug 10, 2013

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.