| #!/bin/bash |
| |
| # This file is part of util-linux. |
| # |
| # This file is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2 of the License, or |
| # (at your option) any later version. |
| # |
| # This file is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| |
| TS_TOPDIR="${0%/*}/../.." |
| TS_DESC="flock" |
| |
| . $TS_TOPDIR/functions.sh |
| ts_init "$*" |
| |
| ts_check_test_command "$TS_CMD_FLOCK" |
| ts_check_prog "pgrep" |
| ts_check_prog "timeout" |
| |
| |
| function do_lock { |
| local opts="$1" |
| local expected_rc="$2" |
| local mesg="$3" |
| |
| $TS_CMD_FLOCK $1 $TS_OUTDIR/lockfile \ |
| echo "$mesg" \ |
| > $TS_OUTPUT 2>&1 |
| |
| local rc="$?" |
| |
| if [ "$rc" == "$expected_rc" ]; then |
| ts_log "Success" |
| else |
| ts_log "Failed [rc=$rc]" |
| fi |
| } |
| |
| # general lock |
| GEN_OUTPUT="$TS_OUTPUT" |
| START=$(date '+%s') |
| # running flock in background is not the best usage example |
| $TS_CMD_FLOCK --shared $TS_OUTDIR/lockfile \ |
| bash -c 'echo "Locking"; sleep 3; echo "Unlocking"' \ |
| > $GEN_OUTPUT 2>&1 & |
| pid=$! |
| |
| # check for running background process |
| if [ "$pid" -le "0" ] || ! kill -s 0 "$pid" &>/dev/null; then |
| ts_die "unable to run flock" |
| fi |
| # the lock should be established when flock has a child |
| timeout 1s bash -c "while ! pgrep -P $pid >/dev/null; do sleep 0.1 ;done" \ |
| || ts_die "timeout waiting for flock child" |
| |
| ts_init_subtest "non-block" |
| do_lock "--nonblock --conflict-exit-code 123" 123 "You will never see this!" |
| ts_finalize_subtest |
| |
| |
| ts_init_subtest "no-fork" |
| do_lock "--no-fork --nonblock --conflict-exit-code 123" 123 "You will never see this!" |
| ts_finalize_subtest |
| |
| |
| ts_init_subtest "shared" |
| do_lock "--shared" 0 "Have shared lock" |
| ts_finalize_subtest |
| |
| |
| # this is the same as non-block test (exclusive lock is the default), but here |
| # we explicitly specify --exclusive on command line |
| ts_init_subtest "exclusive" |
| do_lock "--nonblock --exclusive --conflict-exit-code 123" 123 "You will never see this!" |
| ts_finalize_subtest |
| |
| |
| ts_init_subtest "timeout" |
| do_lock "--timeout 5 --conflict-exit-code 5" 0 "After timeout." |
| END=$(date '+%s') |
| ts_finalize_subtest |
| |
| |
| # expected is 3 seconds (see "sleep 3" for the general lock), but we should not |
| # rely on exact number due to scheduler, machine load, etc. Let's check for |
| # inmterval <3,5>. |
| # |
| ts_init_subtest "time-check" |
| TIMEDIFF=$(( $END - $START )) |
| if [ $TIMEDIFF -lt 3 ]; then |
| ts_log "general lock failed [$TIMEDIFF sec]" |
| elif [ $TIMEDIFF -gt 5 ]; then |
| ts_log "wait too long [$TIMEDIFF sec]" |
| else |
| ts_log "success" |
| fi |
| ts_finalize_subtest "diff ${TIMEDIFF} sec" |
| |
| |
| echo "Unlocked" >> $GEN_OUTPUT |
| ts_finalize |