Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 76813 Details for
Bug 118418
[baselayout] Locking functionality - implementation attached
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Locking implementation, updated
rc-locking.sh (text/plain), 11.65 KB, created by
Oldrich Jedlicka
on 2006-01-11 00:12:05 UTC
(
hide
)
Description:
Locking implementation, updated
Filename:
MIME Type:
Creator:
Oldrich Jedlicka
Created:
2006-01-11 00:12:05 UTC
Size:
11.65 KB
patch
obsolete
># Copyright 2006 Oldrich Jedlicka <oldium.pro@seznam.cz> ># Distributed under the terms of the GNU General Public License v2 > ># Version 1.0 > ># RC functions for using named locks and "thread" variables - variables ># belonging to a subshell. The basic checks for consistency are made as well ># as the cleanup on EXIT from the subshell - this is important if somebody ># terminated the script with SIGINT. Any number of locking within the same ># subshell is allowed, all locks are cleared automatically when the subshell ># terminates. A clean-up function can be defined and is called when the ># defining subshell terminates. ># ># The internal functionality depends on calls to svc_replace_signals - this is ># called every time there is a lock/unlock, a thread variable usage or ># a clean-up function installation. ># ># Errors in locking and unlocking are reported and exit status 1 is returned. ># Exit status 0 is for all successful calls. ># ># NOTE ######################################################################## ># ># Keep in mind that changes in a subshell are not visible to a parent shell! ># ># END NOTE #################################################################### ># ># Example 1: Simple lock ># ># lock "name" || die "Cannot lock" ># ... do something exclusively ># unlock "name" || die "Cannot unlock" ># ... here is no lock active ># ># Example 2: Double lock in the same shell ># ># lock "name" ># lock "name" ># ... do something exclusively ># unlock "name" ># ... still do something exclusively ># unlock "name" ># ... here is no lock active ># ># Example 3: Double locking from the same process, but different subshell ># lock "name" ># ... do something exclusively ># ( ># lock "name" ># ... do something and forget to unlock ># ) ># ... here is the lock from subshell already released ># ... main lock is still active ># unlock "name" ># ... here is no lock active ># ># Example 4: Locking with thread variable ># use_thread_variable VARIABLE ># VARIABLE=10 ># echo $VARIABLE # 10 ># ( ># use_thread_variable VARIABLE ># echo $VARIABLE # Empty string ># VARIABLE=5 ># echo $VARIABLE # 5 ># ) ># echo $VARIABLE # 10 ># ># Example 5: Adding a clean-up function ># func() { ># echo "Clean-up" ># } ># ># ( ># add_cleanup_function func ># echo "Exitting" # Exitting ># ) # Clean-up ># ># NOT CORRECTLY WORKING EXAMPLES ############################################## ># ># Wrong example 1: Normal subshell variable behaviour ># use_thread_variable VARIABLE ># VARIABLE=10 ># echo $VARIABLE # 10 ># ( ># echo $VARIABLE # 10 ># VARIABLE=5 ># echo $VARIABLE # 5 ># ) ># echo $VARIABLE # 10 ># ># Wrong example 2: Locking and thread variables ># use_thread_variable VARIABLE ># VARIABLE=10 ># echo $VARIABLE # 10 ># ( ># echo $VARIABLE # 10 ># lock "name" # Does the job for cleaning the variables ># echo $VARIABLE # Empty string ># VARIABLE=5 ># echo $VARIABLE # 5 ># ) ># echo $VARIABLE # 10 ># > >RC_GOT_LOCKING="yes" > >[[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh > ># bool is_in_list(char *item, char *list) ># ># Returns 0 if the item is in the list, otherwise 1. ># ># To work properly with arrays it has to be called as ># ># is_in_list "value" "$list1[@]" "$list2[@]" ... ># ># For normal operation it can be called as ># ># is_in_list "value" "item1" "item2" "item3" ... ># >is_in_list() { > local x retval=1 item="$1" > shift > for x in "$@" > do > if [[ "$x" == "$item" ]] > then > retval=0 > break > fi > done > return ${retval} >} > ># void use_thread_variable(char *name) ># ># Adds a variable to the list of thread variables. Those variables are ># unset in a subshell. This should be called before anything is assigned ># to the variable. ># >use_thread_variable() { > svc_replace_signals > if ! is_in_list "$1" $SVC_THREADVAR > then > SVC_THREADVAR="$1 $SVC_THREADVAR" > fi >} > ># void add_cleanup_function(char *function) ># ># Adds the function to the list of cleanup actions executed, when the ># current subshell exits. ># >add_cleanup_function() { > svc_replace_signals > if [[ $(type -t "$1") == "function" ]] > then > if ! is_in_list "$1" "${SVC_CLEANUP[@]}" > then > SVC_CLEANUP[${#SVC_CLEANUP}]="$1" > fi > else > echo "$1 is not a function!" > /dev/stderr > fi >} > ># bool trylock(char *name) ># ># Tries to acquire a named lock. Returns 0, if the locking was successful, ># otherwise 1. ># >trylock() { > local path="${svclock}/$1" > local pid retval newcount > > if [[ ! -w ${svclock} ]] > then > # TODO: No locking possible. Error or silently ignore? > return 0 > fi > > add_cleanup_function svc_restore_locks > > pid=$(cat "$path" 2>/dev/null) > pid=( $pid ) > > # Save lock count > > if [[ "$$" == "${pid[0]}" ]] > then > # We are already the owner > svc_save_lock_count "$1" "${pid[1]}" > newcount=$((${pid[1]}+1)) > echo "$$ ${newcount}" > "$path" > retval=$? > else > # We want to get an ownership > svc_save_lock_count "$1" 0 > (set -C; echo "$$ 1" > "$path") 2> /dev/null > retval=$? > fi > return ${retval} >} > ># void lock(char *name) ># ># Acquire the named lock. ># >lock() { > if [[ ! -w ${svclock} ]] > then > return 0 > fi > > while [ 1 ]; do > if trylock "$1"; then > return 0 > else > sleep 0.1 > fi > done >} > ># void unlock(char *name, bool force) ># ># Release the named lock. Returns 1 if the process was not the owner of the ># lock or there was an error during unlocking. ># >unlock() { > local path="${svclock}/$1" > local pid newcount mincount locked error retval=0 > > if [[ ! -w ${svclock} ]] > then > # TODO: No locking possible. Error or silently ignore? > return 0 > fi > > # If we cannot get the contents of the file, it doesn't exist - we are > # not the owner of the file > pid=$(cat "$path" 2>/dev/null) > pid=( $pid ) > > svc_was_locked "$1" && locked=1 || locked=0 > > if [[ "$$" == "${pid[0]}" ]] > then > if [[ $locked -eq 1 ]] > then > newcount=$((${pid[1]}-1)) > mincount=$( svc_get_lock_count "$1" ) > if [[ $newcount -lt $mincount ]] > then > error="Unlocking more times than locking!" > else > if [[ $newcount == 0 ]]; > then > rm -f "$path" > else > echo "$$ ${newcount}" > "$path" > fi > retval=$? > fi > else > error="Unlocking in a subshell without locking!" > fi > elif [[ $locked -eq 1 ]] > then > if [[ -z ${pid[0]} ]] > then > error="Unlocking already unlocked lock!" > else > error="Unlocking not owned lock!" > fi > else > # The lock was not locked by us > if [[ -z "${pid[0]}" ]] > then > error="Unlocking not locked lock!" > else > error="Unlocking not owned lock!" > fi > fi > > if [[ -n $error ]] > then > echo " ${BAD}***${NORMAL} $error" > echo " ${BAD}**${GOOD}*${NORMAL} ${HILITE}HINT:${NORMAL} Maybe you have forgotten to make a lock." > echo " ${BAD}*${GOOD}**${NORMAL} ${HILITE}HINT:${NORMAL} Maybe you did not lock in the same subshell." > echo " ${GOOD}***${NORMAL} ${HILITE}HINT:${NORMAL} If you lock in a subshell, locks recover when you leave it." > retval=1 > fi > > return ${retval} >} > >############################################################################## ># # ># This should be the last public code in here, please add all public above!! # ># # ># *** START PRIVATE CODE *** # ># # >############################################################################## > ># void svc_do_cleanup(void) ># ># This is normal EXIT signal handler. It does all actions defined with ># add_cleanup_function. ># >svc_do_cleanup() { > local name > for name in $SVC_CLEANUP > do > eval $name > done >} > ># void svc_replace_signals(void) ># ># Replace the EXIT signal handler with our implementation. Delete all ># thread variables if the new signal handler is installed. ># >svc_replace_signals() { > local traps tmpfile var > tmpfile=`mktemp /tmp/traps.XXXXXXXX` > if [[ -z $tmpfile ]] > then > # Fatal error! Report and exit > ( RC_QUIET_STDOUT="no" > eerror "Cannot create temporary file in /tmp!" > ) > exit 1 > fi > > # The only way how to get traps from the current shell is to redirect > # output to a temportary file and read it back. > trap -p EXIT > $tmpfile > traps=$( < $tmpfile ) > rm -f $tmpfile > > case $traps in > *'svc_do_cleanup'* ) > # Alredy installed, do nothing > : > ;; > *) > # New installation, clean all known thread variables > SVC_CLEANUP="" > for var in $SVC_THREADVAR > do > unset $var > done > trap svc_do_cleanup EXIT > ;; > esac >} > ># void svc_addlock(char *name) ># ># Adds named lock to lock list. ># >svc_addlock() { > if ! is_in_list "$1" "${SVC_LOCK[@]}" > then > SVC_LOCK[${#SVC_LOCK}]="$1" > fi >} > ># void svc_save_lock_count(char *name, int count) ># ># Save the lock count in the corresponding SVC_LOCKCOUNT_<name> thread ># variable. ># >svc_save_lock_count() { > local lockcountvar lockcount > > lockcountvar="SVC_LOCKCOUNT_"$( bash_variable "$1" ) > use_thread_variable $lockcountvar > lockcount=${!lockcountvar} > > if [[ -z $lockcount ]] > then > if [[ -z $2 ]] > then > lockcount=0 > else > lockcount=$2 > fi > eval "$lockcountvar=$lockcount" > svc_addlock "$1" > fi >} > ># int svc_get_lock_count(char *name) ># ># Get the saved lock count from the thread variable SVC_LOCKCOUNT_<name>. ># Returns the number 0, if the lock was not used before in the current ># subshell. ># ># This function suggests that use_thread_variable() have been called already ># (for example by svc_was_locked() function). ># >svc_get_lock_count() { > local lockcountvar > lockcountvar="SVC_LOCKCOUNT_"$( bash_variable "$1" ) > echo ${!lockcountvar:-0} >} > ># bool svc_was_locked(char *name) ># ># Returns 0 if the lock was used in the current subshell before, otherwise 1. ># >svc_was_locked() { > local lockcountvar > lockcountvar="SVC_LOCKCOUNT_"$( bash_variable "$1" ) > use_thread_variable $lockcountvar > [[ -n ${!lockcountvar} ]] >} > ># void svc_restorelocks() ># ># Restore all locks from the saved values. It has to be called only from the ># installed signal handler svc_do_cleanup, otherwise it will not work! ># >svc_restore_locks() { > local pid name path lockcount > for name in $SVC_LOCK > do > path="${svclock}/$name" > pid=$(cat "$path" 2>/dev/null) > pid=( $pid ) > if [[ "$$" == "${pid[0]}" ]] > then > # Get the lock cound. > lockcount=$( svc_get_lock_count "$name" ) > if [[ $lockcount -eq 0 ]] > then > rm -f "$path" 2> /dev/null > else > echo "$$ ${lockcount}" > "$path" > fi > fi > done >} > > >############################################################################## ># # ># This should be the last code in here, please add all functions above!! # ># # ># *** START LAST CODE *** # ># # >############################################################################## > >############################################################################## ># # ># *** END LAST CODE *** # ># # ># This should be the last code in here, please add all functions above!! # ># # >############################################################################## > > ># vim:ts=4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 118418
:
76646
|
76673
| 76813 |
76815