From 613a337ed4ce87f8ec34c88857a86a1ea6556cb5 Mon Sep 17 00:00:00 2001 From: Ruediger Meier Date: Wed, 7 Mar 2018 00:29:59 +0100 Subject: tests: don't lock fd 1 (stdout), don't use /proc/$$/fd On debian-kfreebsd we've locked stdout which messed up our test logs. Using /proc/*/fd/ is not portable. Even ts_init's test for "/proc/self/fd" does not help because /proc/*/fd behaves strange here: $ ls -l /proc/$$/fd lr--r--r-- 1 rudi user 0 Mar 6 23:11 /proc/2194/fd -> unknown $ file /proc/$$/fd /proc/2194/fd: broken symbolic link to `unknown' ## wtf? $ test -d /proc/$$/fd; echo $? 0 $ ls -l /proc/$$/fd/ ls: cannot access /proc/2194/fd/: No such file or directory ## but $ ls -l /proc/self/fd/ total 0 cr-xr-xr-x 1 root root 0, 3 Mar 6 19:39 0 cr-xr-xr-x 1 root root 0, 4 Mar 6 19:39 1 cr-xr-xr-x 1 root root 0, 5 Mar 6 19:39 2 cr-xr-xr-x 1 root root 0, 6 Mar 6 19:39 3 This is how this patch changes the test output: [...] blkid: partitions probing: [06] sgi ... OK blkid: partitions probing: [07] sun ... OK blkid: partitions probing ... OK (all 7 sub-tests PASSED) -ls: cannot access /proc/66215/fd/: No such file or directory + blkid: mbr-wholedisk ... SKIPPED (missing scsi_debug module (dry-run)) blkid: MD raid0 (whole-disks) ... SKIPPED (losetup not found) blkid: MD raid1 (last partition) ... SKIPPED (missing in PATH: mdadm) blkid: MD raid1 (whole-disks) ... SKIPPED (losetup not found) @@ -343,11 +343,11 @@ dmesg: facilities ... SKIPPED (test_dmesg not found) dmesg: indentation ... SKIPPED (test_dmesg not found) eject: umount ... SKIPPED (eject not found) -ls: cannot access /proc/69561/fd/: No such file or directory -ls: cannot access /proc/69609/fd/: No such file or directory + fdisk: align 512/4K ... SKIPPED (missing scsi_debug module (dry-run)) + fdisk: align 512/4K +alignment_offset ... SKIPPED (missing scsi_debug module (dry-run)) fdisk: align 512/4K +MD ... SKIPPED (missing in PATH: mdadm) fdisk: align 512/512 ... SKIPPED (losetup not found) [...] Signed-off-by: Ruediger Meier --- tests/functions.sh | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'tests/functions.sh') diff --git a/tests/functions.sh b/tests/functions.sh index d1c97e0b6..02f9a94f7 100644 --- a/tests/functions.sh +++ b/tests/functions.sh @@ -15,6 +15,11 @@ # +# Global array to remember all issued lock FDs. It does not seem possible to +# declare this within a function (ts_init_env). +declare -A TS_LOCKFILE_FD + + function ts_abspath { cd $1 pwd @@ -274,10 +279,6 @@ function ts_init_env { TS_NOLOCKS=$(ts_has_option "nolocks" "$*") TS_LOCKDIR="$top_builddir/tests/output" - if [ ! -d "/proc/self/fd" ]; then - TS_NOLOCKS="yes" - fi - # Don't lock if flock(1) is missing type "flock" >/dev/null 2>&1 || TS_NOLOCKS="yes" @@ -693,18 +694,20 @@ function ts_fdisk_clean { } -function ts_get_lock_fd { - local proc=$1 - local lockfile=$2 - - for fd in $(ls /proc/$proc/fd); do - file=$(readlink "/proc/$proc/fd/$fd") - if [ x"$file" = x"$lockfile" ]; then - echo "$fd" - return 0 - fi - done - return 1 +# https://stackoverflow.com/questions/41603787/how-to-find-next-available-file-descriptor-in-bash +function ts_find_free_fd() +{ + local rco + local rci + for fd in {3..200}; do + rco="$(true 2>/dev/null >&${fd}; echo $?)" + rci="$(true 2>/dev/null <&${fd}; echo $?)" + if [[ "${rco}${rci}" = "11" ]]; then + echo "$fd" + return 0 + fi + done + return 1 } function ts_lock { @@ -717,16 +720,17 @@ function ts_lock { fi # Don't lock again - fd=$(ts_get_lock_fd $$ $lockfile) + fd=${TS_LOCKFILE_FD["$resource"]} if [ -n "$fd" ]; then echo "[$$ $TS_TESTNAME] ${resource} already locked!" return 0 fi - fd=$(( $(ls /proc/$$/fd/ | sort | tail -1) + 1)) + fd=$(ts_find_free_fd) || ts_skip "failed to find lock fd" eval "exec $fd>$lockfile" flock --exclusive --timeout 30 $fd || ts_skip "failed to lock $resource" + TS_LOCKFILE_FD["$resource"]="$fd" ###echo "[$$ $TS_TESTNAME] Locked $resource" } @@ -740,10 +744,11 @@ function ts_unlock { return 0 fi - fd=$(ts_get_lock_fd $$ $lockfile) + fd=${TS_LOCKFILE_FD["$resource"]} if [ -n "$fd" ]; then - ###echo "[$$ $TS_TESTNAME] Unlocked $resource" eval "exec $fd<&-" + TS_LOCKFILE_FD["$resource"]="" + ###echo "[$$ $TS_TESTNAME] Unlocked $resource" fi } -- cgit v1.2.3-55-g7522