Files
gniza4linux/lib/locking.sh
shuki 9be7226a35 Rename Targets/Remotes to Sources/Destinations, add Browse to remote editor, fix RichLog crash and crontab sync
- Rename Targets → Sources, Remotes → Destinations across all screens
- Reorganize main menu with logical groupings and separators
- Add Browse button to Base path field in remote editor (local + SSH)
- Fix RichLog IndexError crash when compositor renders with y=-1
- Fix _sync_crontab accidentally wiping crontab via premature remove
- Per-target locking and auto-create local remote base directory

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 04:17:04 +02:00

74 lines
2.0 KiB
Bash

#!/usr/bin/env bash
# gniza4linux/lib/locking.sh — flock-based per-target concurrency control
[[ -n "${_GNIZA4LINUX_LOCKING_LOADED:-}" ]] && return 0
_GNIZA4LINUX_LOCKING_LOADED=1
declare -g LOCK_FD=""
declare -gA _TARGET_LOCK_FDS=()
acquire_lock() {
local lock_file="${LOCK_FILE:-/var/run/gniza.lock}"
local lock_dir; lock_dir=$(dirname "$lock_file")
mkdir -p "$lock_dir" || die "Cannot create lock directory: $lock_dir"
exec {LOCK_FD}>"$lock_file"
if ! flock -n "$LOCK_FD"; then
die "Another gniza process is running (lock: $lock_file)" "$EXIT_LOCKED"
fi
echo $$ >&"$LOCK_FD"
log_debug "Lock acquired: $lock_file (PID $$)"
}
release_lock() {
if [[ -n "$LOCK_FD" ]]; then
flock -u "$LOCK_FD" 2>/dev/null
exec {LOCK_FD}>&- 2>/dev/null
LOCK_FD=""
log_debug "Lock released"
fi
}
# Per-target lock: prevents the same target from running twice,
# but allows different targets to run concurrently.
acquire_target_lock() {
local target_name="$1"
local lock_dir
lock_dir=$(dirname "${LOCK_FILE:-/var/run/gniza.lock}")
mkdir -p "$lock_dir" || die "Cannot create lock directory: $lock_dir"
local lock_file="${lock_dir}/gniza-target-${target_name}.lock"
local fd
exec {fd}>"$lock_file"
if ! flock -n "$fd"; then
log_error "Target '$target_name' is already running (lock: $lock_file)"
exec {fd}>&- 2>/dev/null
return 1
fi
echo $$ >&"$fd"
_TARGET_LOCK_FDS["$target_name"]="$fd"
log_debug "Target lock acquired: $target_name (PID $$)"
}
release_target_lock() {
local target_name="$1"
local fd="${_TARGET_LOCK_FDS[$target_name]:-}"
if [[ -n "$fd" ]]; then
flock -u "$fd" 2>/dev/null
exec {fd}>&- 2>/dev/null
unset '_TARGET_LOCK_FDS[$target_name]'
log_debug "Target lock released: $target_name"
fi
}
release_all_target_locks() {
local name
for name in "${!_TARGET_LOCK_FDS[@]}"; do
release_target_lock "$name"
done
}