Skip to content

Commit 656ca92

Browse files
pks-tgitster
authored andcommitted
builtin/gc: provide hint when maintenance hits a stale schedule lock
When running scheduled maintenance via `git maintenance start`, we acquire a lockfile to ensure that no other scheduled maintenance task is running in the repository concurrently. If so, we do provide an error to the user hinting that another process seems to be running in this repo. There are two important cases why such a lockfile may exist: - An actual git-maintenance(1) process is still running in this repository. - An earlier process may have crashed or was interrupted part way through and has left a stale lockfile behind. In c95547a (builtin/gc: fix crash when running `git maintenance start`, 2024-10-10), we have fixed an issue where git-maintenance(1) would crash with the "start" subcommand, and the underlying bug causes the second scenario to trigger quite often now. Most users don't know how to get out of that situation again though. Ideally, we'd be removing the stale lock for our users automatically. But in the context of repository maintenance this is rather risky, as it can easily run for hours or even days. So finding a clear point where we know that the old process has exited is basically impossible. We have the same issue in other subsystems, e.g. when locking refs. Our lockfile interfaces thus provide the `unable_to_lock_message()` function for exactly this purpose: it provides a nice hint to the user that explains what is going on and how to get out of that situation again by manually removing the file. Adapt git-maintenance(1) to print a similar hint. While we could use the above function, we can provide a bit more context as we know exactly what kind of process would create the lockfile. Reported-by: Miguel Rincon Barahona <[email protected]> Reported-by: Kev Kloss <[email protected]> Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 777489f commit 656ca92

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

builtin/gc.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2887,8 +2887,17 @@ static int update_background_schedule(const struct maintenance_start_opts *opts,
28872887
char *lock_path = xstrfmt("%s/schedule", the_repository->objects->odb->path);
28882888

28892889
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) {
2890+
if (errno == EEXIST)
2891+
error(_("unable to create '%s.lock': %s.\n\n"
2892+
"Another scheduled git-maintenance(1) process seems to be running in this\n"
2893+
"repository. Please make sure no other maintenance processes are running and\n"
2894+
"then try again. If it still fails, a git-maintenance(1) process may have\n"
2895+
"crashed in this repository earlier: remove the file manually to continue."),
2896+
absolute_path(lock_path), strerror(errno));
2897+
else
2898+
error_errno(_("cannot acquire lock for scheduled background maintenance"));
28902899
free(lock_path);
2891-
return error(_("another process is scheduling background maintenance"));
2900+
return -1;
28922901
}
28932902

28942903
for (i = 1; i < ARRAY_SIZE(scheduler_fn); i++) {

t/t7900-maintenance.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,4 +995,12 @@ test_expect_success 'repacking loose objects is quiet' '
995995
)
996996
'
997997

998+
test_expect_success 'maintenance aborts with existing lock file' '
999+
test_when_finished "rm -rf repo" &&
1000+
git init repo &&
1001+
: >repo/.git/objects/schedule.lock &&
1002+
test_must_fail git -C repo maintenance start 2>err &&
1003+
test_grep "Another scheduled git-maintenance(1) process seems to be running" err
1004+
'
1005+
9981006
test_done

0 commit comments

Comments
 (0)