--- keychain-orig 2005-03-10 10:33:18.000000000 -0800 +++ keychain-orig 2005-03-30 20:03:51.969917700 -0800 @@ -322,56 +322,63 @@ tl_faking=true tl_start=0 tl_end=`expr $lockwait \* 10` tl_current=0 fi # Try to lock for $lockwait seconds while [ $lockwait -eq 0 -o $tl_current -lt $tl_end ]; do - if tl_error=`ln -s $$ "$lockf" 2>&1`; then + if tl_error=`(umask 0377; echo $$ > "$lockf") 2>&1`; then havelock=true return 0 fi # advance our timer if [ $lockwait -gt 0 ]; then if $tl_faking; then tl_current=`expr $tl_current + 1` else tl_current=`now $tl_current` fi fi # check for old-style lock; unlikely - if [ -f "$lockf" ]; then + if [ -h "$lockf" ]; then error "please remove old-style lock: $lockf" return 1 fi # read the lock - tl_pid=`readlink "$lockf" 2>/dev/null` - if [ -z "$tl_pid" ]; then - tl_pid=`ls -l "$lockf" 2>/dev/null | awk '{print $NF}'` - fi + tl_pid=`cat "$lockf" 2>/dev/null` if [ -z "$tl_pid" ]; then # lock seems to have disappeared, try again continue fi # test for a stale lock kill -0 "$tl_pid" 2>/dev/null if [ $? != 0 ]; then # Avoid a race condition; another keychain might have started at - # this point. If the pid is the same as the last time we - # checked, then go ahead and remove the stale lock. Otherwise - # remember the pid and try again. + # this point. If the pid is the same as the last time we checked, + # try to remove the stale lock. Otherwise remember the pid and try + # again. if [ "$tl_pid" = "$tl_oldpid" ]; then - warn "removing stale lock for pid $tl_pid" - rm -f "$lockf" + warn "found stale lock for pid $tl_pid" + if (umask 0377; echo $$ > "$lockr") 2>&1; then + tl_pid=`cat "$lockf" 2>/dev/null` + if [ -n "$tl_pid" ]; then + kill -0 "$tl_pid" 2>/dev/null + if [ $? != 0 ]; then + warn "removing stale lock for pid $tl_pid" + rm -f "$lockf" + fi + fi + rm -f "$lockr" + fi else tl_oldpid="$tl_pid" fi # try try again continue fi # sleep for a bit to wait for the keychain process holding the lock @@ -387,17 +394,17 @@ [ -n "$tl_pid" ] || unset tl_pid # ${var+...} relies on set vs. unset error "failed to get the lock${tl_pid+, held by pid $tl_pid}: $tl_error" return 1 } # synopsis: droplock # Drops the lock if we're holding it. droplock() { - [ -n "$lockf" ] && rm -f "$lockf" + $havelock && [ -n "$lockf" ] && rm -f "$lockf" } # synopsis: findpids [prog] # Returns a space-separated list of agent pids. # prog can be ssh or gpg, defaults to ssh. Note that if another prog is ever # added, need to pay attention to the length for Solaris compatibility. findpids() { fp_prog=${1-ssh} @@ -1198,22 +1205,23 @@ # Set filenames *after* parsing command-line options to allow # modification of $keydir and/or $hostopt # # pidf holds the specific name of the keychain .ssh-agent-myhostname file. # We use the new hostname extension for NFS compatibility. cshpidf is the # .ssh-agent file with csh-compatible syntax. lockf is the lockfile, used # to serialize the execution of multiple ssh-agent processes started -# simultaneously +# simultaneously. lockr is the lockfile, used to remove a stale lock. [ -z "$hostopt" ] && hostopt="${HOSTNAME}" [ -z "$hostopt" ] && hostopt=`uname -n 2>/dev/null || echo unknown` pidf="${keydir}/${hostopt}-sh" cshpidf="${keydir}/${hostopt}-csh" lockf="${keydir}/${hostopt}-lock" +lockr="${keydir}/${hostopt}-repair" # Don't use color if there's no terminal on stdout if [ -n "$OFF" ]; then tty <&1 >/dev/null 2>&1 || unset BLUE CYAN GREEN OFF RED fi # versinfo uses qprint, which honors --quiet versinfo