summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/scripts/filemutexdemo1.sh
diff options
context:
space:
mode:
authorApril Chin <April.Chin@Sun.COM>2008-12-27 14:59:38 -0800
committerApril Chin <April.Chin@Sun.COM>2008-12-27 14:59:38 -0800
commit7c2fbfb345896881c631598ee3852ce9ce33fb07 (patch)
tree4b173b5657508562dfc0aa05f7d056d1e9add505 /usr/src/lib/libshell/common/scripts/filemutexdemo1.sh
parent6071ac1de68fed78e1e10052045bbb5f1732a263 (diff)
downloadillumos-joyent-7c2fbfb345896881c631598ee3852ce9ce33fb07.tar.gz
PSARC/2008/094 ksh93 Update 1
PSARC/2008/344 ksh93 Integration Update 1 Amendments 1 PSARC/2008/589 Remove /usr/bin/printf from PSARC case 2008 094 6619428 *ksh93* RFE: Update ksh93 in Solaris to ast-ksh.2008-11-04 6788659 RFE: Update libpp in Solaris to ast-open.2008-07-25 6561901 RFE: Add "shcomp" (shell script compiler) + kernel module to exec binary sh code 6599668 RFE: Move consumers of alias.sh over to ksh93 6595183 *ksh93* RFE: Update ksh93-integration demo code 6775901 *ksh93* no C message catalogs are generated for ksh93 6451262 *sleep* RFE: /usr/bin/sleep should support floating-point values 6687139 *ksh93* command substitution, exec, and stdout redirection cause allocation loop 6703761 *ksh93* crashes in script containing uncommon output redirections 6715496 *ksh93* SEGVs on array reinitialization 6713682 *ksh93* Creating a compound variable in a subshell "bleeds through" to the calling subshell 6672350 *ksh93* causes parent shell to die when child shell is suspended 6745015 *ksh93* VARIABLE=`command substitution` assignment is not reliable on OpenSolaris 6710205 *ksh93* problem with command substitution (within back quotes) containing \$' 6737600 *ksh93* exits debugger when user presses ctrl-c 6748645 *ksh93* fc -l -e - is mis-parsed, outputs wrong error message "-e - requires single argument" 6754020 *ksh93* does weird '[' expansion 6753538 *ksh93* umask modification leaks out of a ksh93 subshell 6766246 *ksh93* bug in pattern matching 6763594 *ksh93* executes command after "command" builtin twice on failure 6762665 *ksh93* Difficult-to-reproduce SIGSEGV in ksh93
Diffstat (limited to 'usr/src/lib/libshell/common/scripts/filemutexdemo1.sh')
-rw-r--r--usr/src/lib/libshell/common/scripts/filemutexdemo1.sh267
1 files changed, 267 insertions, 0 deletions
diff --git a/usr/src/lib/libshell/common/scripts/filemutexdemo1.sh b/usr/src/lib/libshell/common/scripts/filemutexdemo1.sh
new file mode 100644
index 0000000000..1de54a92fc
--- /dev/null
+++ b/usr/src/lib/libshell/common/scripts/filemutexdemo1.sh
@@ -0,0 +1,267 @@
+#!/usr/bin/ksh93
+
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# filemutexdemo1 - a simple locking demo which supports read/write
+# locks and critical sections (like JAVA's "syncronized" keyword)
+#
+
+# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
+export PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
+
+# Make sure all math stuff runs in the "C" locale to avoid problems
+# with alternative # radix point representations (e.g. ',' instead of
+# '.' in de_DE.*-locales). This needs to be set _before_ any
+# floating-point constants are defined in this script).
+if [[ "${LC_ALL}" != "" ]] ; then
+ export \
+ LC_MONETARY="${LC_ALL}" \
+ LC_MESSAGES="${LC_ALL}" \
+ LC_COLLATE="${LC_ALL}" \
+ LC_CTYPE="${LC_ALL}"
+ unset LC_ALL
+fi
+export LC_NUMERIC=C
+
+# Definition for a mutex which uses the filesystem for locking
+typeset -T filemutex_t=(
+ typeset name
+
+ typeset lock_dirname
+
+ typeset locked_exclusive="false"
+ typeset locked_shared="false"
+
+ # keep track of subshell level. The problem is that we do not know a
+ # way to figure out whether someone calls "unlock" in a subshell and then
+ # leaves the subshell and calls "unlock" again
+ integer subshell=-1
+
+ typeset lock_dirname
+
+ # create a filemutex instance (including lock directory)
+ function create
+ {
+ # make sure we return an error if the init didn't work
+ set -o errexit
+
+ [[ "$1" == "" ]] && return 1
+
+ _.name="$1"
+ _.lock_dirname="/tmp/filemutex_t_${_.name}.lock"
+
+ mkdir "${_.lock_dirname}"
+
+ # last entry, used to mark the mutex as initalised+valid
+ (( _.subshell=.sh.subshell ))
+ return 0
+ }
+
+ # use a filemutex instance (same as "create" but without creating
+ # the lock directory)
+ function create_child
+ {
+ # make sure we return an error if the init didn't work
+ set -o errexit
+
+ [[ "$1" == "" ]] && return 1
+
+ _.name="$1"
+ _.lock_dirname="/tmp/filemutex_t_${_.name}.lock"
+
+ # last entry, used to mark the mutex as initalised+valid
+ (( _.subshell=.sh.subshell ))
+ return 0
+ }
+
+ function check_subshell
+ {
+ (( _.subshell == .sh.subshell )) && return 0
+ print -u2 -f "filemutex_t.%s(%s): Wrong subshell level\n" "$1" "${_.name}"
+ return 1
+ }
+
+ function try_lock_shared
+ {
+ _.check_subshell "try_lock_shared" || return 1
+
+ mkdir "${_.lock_dirname}/shared_${PPID}_$$" 2>/dev/null || return 1
+ _.locked_shared="true"
+ return 0
+ }
+
+ function lock_shared
+ {
+ float interval=0.2
+
+ _.check_subshell "lock_shared" || return 1
+
+ while ! _.try_lock_shared ; do sleep ${interval} ; (( interval+=interval/10. )) ; done
+ return 0
+ }
+
+ function try_lock_exclusive
+ {
+ _.check_subshell "try_lock_exclusive" || return 1
+
+ rmdir "${_.lock_dirname}" 2>/dev/null || return 1
+ _.locked_exclusive="true"
+ return 0
+ }
+
+ function lock_exclusive
+ {
+ float interval=0.2
+
+ _.check_subshell "lock_exclusive" || return 1
+
+ while ! _.try_lock_exclusive ; do sleep ${interval} ; (( interval+=interval/10. )) ; done
+ return 0
+ }
+
+ # critical section support (like java's "synchronized" keyword)
+ function synchronized
+ {
+ integer retcode
+
+ _.check_subshell "synchronized" || return 1
+
+ _.lock_exclusive
+
+ "$@"
+ (( retcode=$? ))
+
+ _.unlock
+
+ return ${retcode}
+ }
+
+ # critical section support with shared lock
+ function synchronized_shared
+ {
+ integer retcode
+
+ _.check_subshell "synchronized_shared" || return 1
+
+ _.lock_shared
+
+ "$@"
+ (( retcode=$? ))
+
+ _.unlock
+
+ return ${retcode}
+ }
+
+ function unlock
+ {
+ # return an error if rmdir/mkdir/check_subshell fail...
+ set -o errexit
+
+ _.check_subshell "unlock"
+
+ if ${_.locked_shared} ; then
+ rmdir "${_.lock_dirname}/shared_${PPID}_$$"
+ _.locked_shared="false"
+ return 0
+ elif ${_.locked_exclusive} ; then
+ mkdir "${_.lock_dirname}"
+ _.locked_exclusive="false"
+ return 0
+ fi
+
+ print -u2 -f "filemutex_t.unlock(%s): mutex '%s' not locked." "$1" "${_.name}"
+ return 1
+ }
+
+ # destroy mutex if noone is using it anymore (not the same as "unset" !!))
+ function destroy
+ {
+ _.check_subshell "destroy" || return 1
+
+ (${_.locked_exclusive} || ${_.locked_shared}) && _.unlock
+ rmdir "${_.lock_dirname}"
+ return 0
+ }
+)
+
+# main
+builtin mkdir
+builtin rmdir
+
+print "## Start."
+
+typeset -r mymutexname="hello_world"
+
+filemutex_t fs
+
+fs.create "${mymutexname}" || print -u2 "Mutex init failed."
+
+print "# Starting child which keeps an exclusive lock for 10 seconds..."
+(
+ filemutex_t child_fs
+
+ child_fs.create_child "${mymutexname}"
+
+ child_fs.lock_exclusive
+ sleep 10
+ child_fs.unlock
+) &
+
+sleep 1
+
+printf "%T: # Waiting to obtain a shared lock...\n"
+fs.lock_shared
+printf "%T: # Obtained shared lock\n"
+
+printf "fs.locked_exclusive=%s, fs.locked_shared=%s\n" "${fs.locked_exclusive}" "${fs.locked_shared}"
+
+ls -lad /tmp/filemutex*/*
+
+printf "%T: # Executing child which runs printf '|%%s|\\\n' 'hello' 'world' inside a synchronized section\n"
+(
+ filemutex_t child_fs
+
+ child_fs.create_child "${mymutexname}"
+
+ child_fs.synchronized printf '|%s|\n' 'hello' 'world'
+) &
+
+printf "%T: # Sleeping 5 secs while holding the shared lock...\n"
+sleep 5.
+
+printf "%T: # Releasing shared lock...\n"
+fs.unlock
+
+sleep 5.
+print "# Destroying lock..."
+fs.destroy
+
+print "## Done."
+
+exit 0