From 1eeb12756ba5fb8a4b4802ad3931f99e64ffda2a Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Fri, 26 Jun 2020 01:06:29 -0700 Subject: [PATCH] shlib: add and use clear_stale_ref_locks function If git is killed during a ref update operation, it may leave behind a ref lock file. Add a new clear_stale_ref_locks function to find and remove any of these stale left-behind *.lock files. Call clear_stale_ref_locks as part of the "remove_crud" operation durin gc, part of the cleanup operation when restarting a failed clone and as part of the cleanup operation before doing a mirror update. Since Girocco now makes it a point to (mostly) maintain refs in a packed state, the check and removal will always be relatively quick and cheap to do. Signed-off-by: Kyle J. McKay --- jobd/gc.sh | 9 ++++++--- jobd/update.sh | 3 +++ shlib.sh | 20 ++++++++++++++++++++ taskd/clone.sh | 3 +++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/jobd/gc.sh b/jobd/gc.sh index c3393f0..58702b7 100755 --- a/jobd/gc.sh +++ b/jobd/gc.sh @@ -481,6 +481,9 @@ remove_crud() { # there were a lot of refs. rm -f FETCH_HEAD + # Remove any stale ref locks + clear_stale_ref_locks + # remove any existing pack_is_complete_test or repack subdirectories # If either exists when this function is called it's crud rm -rf pack_is_complete_test repack objects/pack/repack @@ -809,15 +812,15 @@ lock_gc # At this point, if .allowgc or .gc_failed exists, it's now crud to be removed rm -f .allowgc .gc_failed +# Always get rid of crud +remove_crud + # Ideally we would do this in post-receive, but that would mean duplicating the # logic so it's available in the chroot jail and that's highly undesirable # Instead, since the first gc will be triggered immediately following the first # push, we do the check here as it's quick and harmless if HEAD is already valid check_and_set_head || : -# Always get rid of crud -remove_crud - # Always perform reflogs maintenance coalesce_reflogs prune_reflogs diff --git a/jobd/update.sh b/jobd/update.sh index 2454bda..c46083a 100755 --- a/jobd/update.sh +++ b/jobd/update.sh @@ -133,6 +133,9 @@ progress "+ [$proj] update ($(date))" # Any pre-existing FETCH_HEAD from a previous fetch, failed or not, is garbage rm -f FETCH_HEAD +# Remove any stale ref locks +clear_stale_ref_locks + # A previous failed update attempt can leave a huge tmp_pack_XXXXXX file behind. # Since no pushes are allowed to mirrors, we know that any such files that exist # at this point in time are garbage and can be safely deleted, we do not even diff --git a/shlib.sh b/shlib.sh index 2de11ae..80a2e00 100644 --- a/shlib.sh +++ b/shlib.sh @@ -920,6 +920,26 @@ check_and_set_needsgc() { fi } +# current directory must already be set to Git repository +# remove any existing stale .lock files anywhere in the refs hierarchy +# mirror .lock files are considered "stale" after 60m whereas push projects +# need 12h for a .lock file to be considered stale. +clear_stale_ref_locks() { + # Quick sanity check just in case + [ -f HEAD ] && [ -s HEAD ] && [ -d objects ] && [ -d refs ] || return 1 + _stale=60 + [ ! -e .nofetch ] || _stale=720 + # Clear any stale top-level ref locks + find . -maxdepth 1 -name '*?.lock' -type f -mmin +$_stale -exec rm -f '{}' + >/dev/null 2>&1 || : + if [ -d worktrees ]; then + # Clear any worktrees stale top-level ref locks + find -H worktrees -mindepth 2 -maxdepth 2 -name '*?.lock' -type f -mmin +$_stale -exec rm -f '{}' + >/dev/null 2>&1 || : + fi + # Clear any stale ref locks within the refs hierarchy itself + find -H refs -mindepth 1 -name '*?.lock' -type f -mmin +$_stale -exec rm -f '{}' + >/dev/null 2>&1 || : + return 0 +} + # A well-known UTF-8 locale is required for some of the fast-import providers # in order to avoid mangling characters. Ideally we could use "POSIX.UTF-8" # but that is not reliably UTF-8 but rather usually US-ASCII. diff --git a/taskd/clone.sh b/taskd/clone.sh index 296b696..14e6733 100755 --- a/taskd/clone.sh +++ b/taskd/clone.sh @@ -149,6 +149,9 @@ cleanup_failed_clone() { # now garbage to be removed rm -f FETCH_HEAD + # Remove any stale ref locks + clear_stale_ref_locks + # Remove any left-over svn dir from a previous failed attempt rm -rf svn -- 2.11.4.GIT