1#! /bin/sh 2# Shell-based mutex using mkdir. This script is used in make to prefer 3# serialized execution to avoid consuming too much RAM. If reusing it, 4# bear in mind that the lock-breaking logic is not race-free, so disable 5# it in err() if concurrent execution could cause more serious problems. 6 7self=`basename $0` 8lockdir="$1" prog="$2"; shift 2 || exit 1 9 10# Remember when we started trying to acquire the lock. 11count=0 12 13err () { 14 if test -f $lockdir/lock-$1.$$; then 15 rm -rf $lockdir 16 echo "$self: *** (PID $$) removed stale $lockdir" >&2 17 18 # Possible variant for uses where races are more problematic: 19 #echo "$self: *** (PID $$) giving up, maybe rm -r $lockdir" >&2 20 #exit 42 21 else 22 touch $lockdir/lock-$1.$$ 23 fi 24} 25 26until mkdir "$lockdir" 2>/dev/null; do 27 # Say something periodically so the user knows what's up. 28 if [ `expr $count % 30` = 0 ]; then 29 # Check for valid lock. 30 if pid=`cat $lockdir/pid 2>/dev/null` && kill -0 $pid 2>/dev/null; then 31 echo "$self: (PID $$) waiting $count sec to acquire $lockdir from PID $pid" >&2 32 elif test -z "$pid"; then 33 echo "$self: (PID $$) cannot read $lockdir/pid" >&2 34 err nopid 35 else 36 echo "$self: (PID $$) cannot signal $lockdir owner PID $pid" >&2 37 err dead 38 fi 39 fi 40 sleep 1 41 count=`expr $count + 1` 42done 43 44trap 'rm -rf "$lockdir"' 0 45echo $$ > $lockdir/pidT && mv $lockdir/pidT $lockdir/pid 46echo "$self: (PID $$) acquired $lockdir after $count seconds" >&2 47 48echo $prog "$@" 49$prog "$@" 50 51# The trap runs on exit. 52