]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
tests: don't lock fd 1 (stdout), don't use /proc/$$/fd
authorRuediger Meier <ruediger.meier@ga-group.nl>
Tue, 6 Mar 2018 23:29:59 +0000 (00:29 +0100)
committerRuediger Meier <ruediger.meier@ga-group.nl>
Wed, 7 Mar 2018 17:41:04 +0000 (18:41 +0100)
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 <ruediger.meier@ga-group.nl>
tests/functions.sh

index d1c97e0b6faecec4ca896da93b5ddc333a5f09da..02f9a94f7e9ce69e27f8be691579e29a82983873 100644 (file)
 #
 
 
+# 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
 }