Experimental implementation to wait rehash until acquiring lock

For now the code is using traditional pseudo locking mechanism
based on `noclobber`.
This commit is contained in:
Yamashita, Yuu 2018-04-19 01:02:16 +00:00
parent 63c4b7f45c
commit a6c15fb242

View file

@ -10,29 +10,49 @@ PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.pyenv-shim"
# Create the shims directory if it doesn't already exist.
mkdir -p "$SHIM_PATH"
# Ensure only one instance of pyenv-rehash is running at a time by
# setting the shell's `noclobber` option and attempting to write to
# the prototype shim file. If the file already exists, print a warning
# to stderr and exit with a non-zero status.
set -o noclobber
{ echo > "$PROTOTYPE_SHIM_PATH"
} 2>| /dev/null ||
{ if [ -w "$SHIM_PATH" ]; then
acquire_lock() {
# Ensure only one instance of pyenv-rehash is running at a time by
# setting the shell's `noclobber` option and attempting to write to
# the prototype shim file. If the file already exists, print a warning
# to stderr and exit with a non-zero status.
local ret
set -o noclobber
echo > "$PROTOTYPE_SHIM_PATH" 2>| /dev/null || ret=1
set +o noclobber
[ -z "${ret}" ]
}
# If we were able to obtain a lock, register a trap to clean up the
# prototype shim when the process exits.
trap release_lock EXIT
remove_prototype_shim() {
rm -f "$PROTOTYPE_SHIM_PATH"
}
release_lock() {
remove_prototype_shim
}
unset acquired
for _ in $(seq "${PYENV_REHASH_LOCK_TIMEOUT:-60}"); do
if acquire_lock 2>/dev/null; then
acquired=1
break
else
# POSIX sleep(1) doesn't provides time precision of subsecond
sleep 1
fi
done
if [ -z "${acquired}" ]; then
if [ -w "$SHIM_PATH" ]; then
echo "pyenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists"
else
echo "pyenv: cannot rehash: $SHIM_PATH isn't writable"
fi
exit 1
} >&2
set +o noclobber
# If we were able to obtain a lock, register a trap to clean up the
# prototype shim when the process exits.
trap remove_prototype_shim EXIT
remove_prototype_shim() {
rm -f "$PROTOTYPE_SHIM_PATH"
}
fi
# The prototype shim file is a script that re-execs itself, passing
# its filename and any arguments to `pyenv exec`. This file is