From a6c15fb2424148fe1247dcf0fd2186fd4b46bc4d Mon Sep 17 00:00:00 2001 From: "Yamashita, Yuu" Date: Thu, 19 Apr 2018 01:02:16 +0000 Subject: [PATCH] Experimental implementation to wait rehash until acquiring lock For now the code is using traditional pseudo locking mechanism based on `noclobber`. --- libexec/pyenv-rehash | 56 ++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/libexec/pyenv-rehash b/libexec/pyenv-rehash index 0c822e51..b03c0d1b 100755 --- a/libexec/pyenv-rehash +++ b/libexec/pyenv-rehash @@ -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