Files
nvm/test/fast/Unit tests/nvm_release_install_lock
Jordan Harband 809f3ee5ab [New] nvm install: serialize concurrent installs of the same version
Two `nvm install <same version>` runs could race on the version directory
- one removing or replacing it while the other reads or writes it.
Take a per-version advisory lock
(an atomically-created directory under $NVM_DIR/.cache locks)
around the binary/source install,
so a second run of the same version waits for the first;
installs of different versions never contend.

NVM_INSTALL_LOCK_TIMEOUT (seconds, default 600) bounds the wait,
after which nvm reports the lock path so a lock left by a killed install can be removed.
NVM_INSTALL_LOCK_STALE (minutes, default 0 / off)
opts into automatically stealing a lock older than that,
for unattended or CI use.
2026-07-24 10:55:58 -07:00

36 lines
1.2 KiB
Bash
Executable File

#!/bin/sh
cleanup() {
[ -n "${NVM_DIR}" ] && [ -d "${NVM_DIR}" ] && rm -rf "${NVM_DIR}"
unset -f die cleanup
unset NVM_DIR NVM_INSTALL_LOCK version lock
}
die() { echo "$@" ; cleanup ; exit 1; }
: nvm.sh
\. ../../../nvm.sh
type nvm_release_install_lock > /dev/null 2>&1 || die 'nvm_release_install_lock is not available'
NVM_DIR="$(mktemp -d)"
[ -n "${NVM_DIR}" ] || die 'unable to create temp NVM_DIR'
version='v20.0.0'
lock="$(nvm_cache_dir)/locks/$(nvm_install_lock_name "${version}")"
# Releasing when nothing is held is a no-op that succeeds.
unset NVM_INSTALL_LOCK
nvm_release_install_lock || die 'releasing with no lock held should succeed'
# After acquiring, releasing removes the lock directory and clears the marker.
nvm_acquire_install_lock "${version}" || die 'setup: acquire failed'
[ -d "${lock}" ] || die 'setup: lock dir should exist after acquire'
nvm_release_install_lock || die 'release should succeed'
[ ! -d "${lock}" ] || die 'release should remove the lock directory'
[ -z "${NVM_INSTALL_LOCK-}" ] || die 'release should clear NVM_INSTALL_LOCK'
# Releasing again is a harmless no-op.
nvm_release_install_lock || die 'a second release should be a no-op'
cleanup