From d4dbd0c127b292fcac50afcd708699d5048a8e34 Mon Sep 17 00:00:00 2001 From: Levente Polyak <anthraxx@archlinux.org> Date: Tue, 14 Nov 2023 19:23:28 +0100 Subject: [PATCH] fix(db-functions): acquire a lock around git clone and fetch operations An initial git clone and especially a git fetch operation can occur concurrently through multiple packagers and processes. Guard these git operations with a fetch lock inside the actual git repository as well as a special lock stored in the shared global lock directory before starting an initial clone. Fixes #49 Signed-off-by: Levente Polyak <anthraxx@archlinux.org> --- config | 1 + config.local.git | 1 + db-functions-git | 18 +++++++++++++++--- test/lib/common.bash | 1 + 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/config b/config index e4af6b8..d8b8458 100644 --- a/config +++ b/config @@ -32,6 +32,7 @@ SOURCE_CLEANUP_KEEP=14 LOCK_DELAY=10 LOCK_TIMEOUT=300 +LOCK_DIR="/var/tmp" STAGING="$HOME/staging" export TMPDIR="/var/tmp" diff --git a/config.local.git b/config.local.git index a107a60..a17a8ee 100644 --- a/config.local.git +++ b/config.local.git @@ -68,3 +68,4 @@ GIT_STATE_REPO="/srv/repos/state" GITUSER="" GIT_PACKAGES_CACHE="/srv/repos/pkg-cache" +LOCK_DIR="/srv/repos/lock" diff --git a/db-functions-git b/db-functions-git index 3cb138c..1bf6340 100644 --- a/db-functions-git +++ b/db-functions-git @@ -66,15 +66,27 @@ fetch_pkgbuild() { # avoid git operations asking for terminal input export GIT_TERMINAL_PROMPT=0 + # double checked locking for fresh clones if [[ ! -d $target ]]; then - if ! arch_git -c core.sharedRepository=group clone --origin origin --bare --mirror "${src}" "${target}"; then - return 1 + lock 8 "${LOCK_DIR}/repo-clone-${pkgbase}.lock" "Locking git clone for ${pkgbase}" + if [[ ! -d $target ]]; then + if ! arch_git -c core.sharedRepository=group clone --origin origin --bare --mirror "${src}" "${target}"; then + lock_close 8 + return 1 + fi + lock_close 8 + return 0 fi - return 0 + lock_close 8 fi + + lock 8 "${target}/.git/dbscripts.lock" "Locking git repo ${pkgbase}" if ! arch_git -C "${target}" fetch --prune --prune-tags; then + lock_close 8 return 1 fi + lock_close 8 + return 0 } diff --git a/test/lib/common.bash b/test/lib/common.bash index aa5552e..40b134e 100644 --- a/test/lib/common.bash +++ b/test/lib/common.bash @@ -205,6 +205,7 @@ setup() { GIT_PACKAGING_REPOS_URL="${TMP}/git-packages" GIT_STATE_REPO="${TMP}/repository" GIT_PACKAGES_CACHE="${TMP}/git-pkg-repos" + LOCK_DIR="${TMP}/lock" GITUSER="" AUTHORS="${TMP}/authors.conf" PACKAGER_DOMAIN=localhost -- GitLab