Description: Use flock for a more robust lock file handling
Debian-Bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=568565
Author: Michael Biebl <biebl@debian.org>
diff --git a/pm/HOWTO.hooks b/pm/HOWTO.hooks
index ad7d4a7..ce9e8c4 100644
--- a/pm/HOWTO.hooks
+++ b/pm/HOWTO.hooks
@@ -99,7 +99,7 @@ the hook. This will make the following convenience functions available:
 2:  spin_lock
 	Wrapper around try_lock.  Second parameter is the number of seconds 
 	to wait for the lock before giving up.  If no second parameter
-	is passed, this function will wait forever.
+	is passed, this function will wait for 60 seconds.
 3:  release_lock
 	Release a previously acquired lock.  First parameter is the name of the
 	lock.
diff --git a/pm/functions.in b/pm/functions.in
index 8388c65..b07bf44 100644
--- a/pm/functions.in
+++ b/pm/functions.in
@@ -22,13 +22,13 @@ is_set "${PM_DEBUG}" && set -x
 try_lock()
 {
 	# $1 = file to use as lockfile
-	# $2 (optional) content to write to the lockfile,
-	# extra newline will be appended
+	local lock="${LOCKDIR}/${1##*/}"
+
 	# make sure the directory where the lockfile should be exists
 	mkdir -p "${LOCKDIR}"
-	local lock="${LOCKDIR}/${1##*/}"
-	# we use noclobber to make sure there are no race conditions
-	(set -o noclobber; echo "${2}" > "${lock}") 2> /dev/null || return 1
+	touch "${lock}"
+	exec 3<"${lock}"
+	flock -x -n 3 || return 1
 	return 0
 }
 
@@ -37,13 +37,15 @@ try_lock()
 spin_lock()
 {
 	# $1 = lockfile
-	# $2 = optional timeout
-	local elapsed=0
-	while ! try_lock $1; do
-		[ "x$2" != "x" ] && [ $(( $elapsed == $2 )) -ne 0 ] && return 1
-		elapsed=$(($elapsed + 1))
-		sleep 1;
-	done
+	# $2 = optional timeout (default is 60 secs)
+	local lock="${LOCKDIR}/${1##*/}"
+	local timeout="${2:-60}"
+
+	mkdir -p "${LOCKDIR}"
+	touch "${lock}"
+	exec 3<"${lock}"
+	flock -x -w "${timeout}" 3 || return 1
+	return 0
 }
 
 # release the lock
