From 8fa68a91e02708884d7fde6d1467b1edf9a5131c Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Wed, 10 Jun 2020 11:58:54 -0700 Subject: [PATCH] gc-util-functions: migrate v_lock_gc into gc utility library Move the `pidactive`, `createlock` and `v_lock_gc` functions from `gc.sh` into `gc-util-functions.sh` to make them available for use from other script files. Signed-off-by: Kyle J. McKay --- jobd/gc-util-functions.sh | 79 ++++++++++++++++++++++++++++++++++++++++++++++ jobd/gc.sh | 80 ----------------------------------------------- 2 files changed, 79 insertions(+), 80 deletions(-) diff --git a/jobd/gc-util-functions.sh b/jobd/gc-util-functions.sh index b469f75..7feb14f 100755 --- a/jobd/gc-util-functions.sh +++ b/jobd/gc-util-functions.sh @@ -11,6 +11,85 @@ packopts="--depth=50 --window=50 --window-memory=${var_window_memory:-1g}" quiet="-q"; [ "${show_progress:-0}" = "0" ] || quiet= +pidactive() { + if _result="$(kill -0 "$1" 2>&1)"; then + # process exists and we have permission to signal it + return 0 + fi + case "$_result" in *"not permitted"*) + # we do not have permission to signal the process + return 0 + esac + # process does not exist + return 1 +} + +createlock() { + # A .lock file should only exist for much less than a second. + # If we see a stale lock file (> 1h old), remove it and then, + # just in case, wait 30 seconds for any process whose .lock + # we might have just removed (it's racy) to finish doing what + # should take much less than a second to do. + _stalelock="$(find -L "$1.lock" -maxdepth 1 -mmin +60 -print 2>/dev/null)" || : + if [ -n "$_stalelock" ]; then + rm -f "$_stalelock" + sleep 30 + fi + for _try in p p n; do + if (set -C; >"$1.lock") 2>/dev/null; then + echo "$1.lock" + return 0 + fi + # delay and try again + [ "$_try" != "p" ] || sleep 1 + done + # cannot create lock file + return 1 +} + +# Create a gc.pid lockfile +# $1 => name of variable to store result in +# On success: +# variable named by $1 will contain the name of the newly create lockfile (i.e. "gc.pid") +# On failure: +# variable named by $1 will contain the failure reason +v_lock_gc() { + # be compatibile with gc.pid file from newer Git releases + _lockf='gc.pid' + _hn="$(hostname)" + _active= + if [ "$(createlock "$_lockf")" ]; then + # If $_lockf is: + # 1) less than 12 hours old + # 2) contains two fields (pid hostname) NO trailing NL + # 3) the hostname is different OR the pid is still alive + # then we exit as another active process is holding the lock + if [ "$(find -L "$_lockf" -maxdepth 1 -mmin -720 -print 2>/dev/null)" ]; then + _apid= + _ahost= + read -r _apid _ahost _ajunk <"$_lockf" || : + if [ "$_apid" ] && [ "$_ahost" ]; then + if [ "$_ahost" != "$_hn" ] || pidactive "$_apid"; then + _active=1 + fi + fi + fi + else + eval "$1="'"unable to create $_lockf.lock file"' + return 1 + fi + if [ -n "$_active" ]; then + rm -f "$_lockf.lock" + eval "$1="'"gc already running on machine '\''$_ahost'\'' pid '\''$_apid'\''"' + return 1 + fi + printf "%s %s" "$$" "$_hn" >"$_lockf.lock" + chmod 0664 "$_lockf.lock" + mv -f "$_lockf.lock" "$_lockf" + eval "$1="'"$_lockf"' + return 0 +} + # make sure combine-packs uses the correct Git executable run_combine_packs() { PATH="$var_git_exec_path:$cfg_basedir/bin:$PATH" @basedir@/jobd/combine-packs.sh "$@" diff --git a/jobd/gc.sh b/jobd/gc.sh index bb3de2d..c3393f0 100755 --- a/jobd/gc.sh +++ b/jobd/gc.sh @@ -25,42 +25,6 @@ umask 002 [ "$cfg_permission_control" != "Hooks" ] || umask 000 clean_git_env -pidactive() { - if _result="$(kill -0 "$1" 2>&1)"; then - # process exists and we have permission to signal it - return 0 - fi - case "$_result" in *"not permitted"*) - # we do not have permission to signal the process - return 0 - esac - # process does not exist - return 1 -} - -createlock() { - # A .lock file should only exist for much less than a second. - # If we see a stale lock file (> 1h old), remove it and then, - # just in case, wait 30 seconds for any process whose .lock - # we might have just removed (it's racy) to finish doing what - # should take much less than a second to do. - _stalelock="$(find -L "$1.lock" -maxdepth 1 -mmin +60 -print 2>/dev/null)" || : - if [ -n "$_stalelock" ]; then - rm -f "$_stalelock" - sleep 30 - fi - for _try in p p n; do - if (set -C; >"$1.lock") 2>/dev/null; then - echo "$1.lock" - return 0 - fi - # delay and try again - [ "$_try" != "p" ] || sleep 1 - done - # cannot create lock file - return 1 -} - # The pre-receive script creates one ref log file per push but we want them to # be coalesced into one ref log file per day. We are guaranteed that any files # we find to coalesce are NOT currently being written to since they are always @@ -367,50 +331,6 @@ pack_is_complete() { } # On return a "$lockf" will have been created that must be removed when gc is done -# Create a gc.pid lockfile -# $1 => name of variable to store result in -# On success: -# variable named by $1 will contain the name of the newly create lockfile (i.e. "gc.pid") -# On failure: -# variable named by $1 will contain the failure reason -v_lock_gc() { - # be compatibile with gc.pid file from newer Git releases - _lockf='gc.pid' - _hn="$(hostname)" - _active= - if [ "$(createlock "$_lockf")" ]; then - # If $_lockf is: - # 1) less than 12 hours old - # 2) contains two fields (pid hostname) NO trailing NL - # 3) the hostname is different OR the pid is still alive - # then we exit as another active process is holding the lock - if [ "$(find -L "$_lockf" -maxdepth 1 -mmin -720 -print 2>/dev/null)" ]; then - _apid= - _ahost= - read -r _apid _ahost _ajunk <"$_lockf" || : - if [ "$_apid" ] && [ "$_ahost" ]; then - if [ "$_ahost" != "$_hn" ] || pidactive "$_apid"; then - _active=1 - fi - fi - fi - else - eval "$1="'"unable to create $_lockf.lock file"' - return 1 - fi - if [ -n "$_active" ]; then - rm -f "$_lockf.lock" - eval "$1="'"gc already running on machine '\''$_ahost'\'' pid '\''$_apid'\''"' - return 1 - fi - printf "%s %s" "$$" "$_hn" >"$_lockf.lock" - chmod 0664 "$_lockf.lock" - mv -f "$_lockf.lock" "$_lockf" - eval "$1="'"$_lockf"' - return 0 -} - -# On return a "$lockf" will have been created that must be removed when gc is done lock_gc() { v_lock_gc _lockresult || { echo >&2 "[$proj] $_lockresult" -- 2.11.4.GIT