* tests/init.sh (remove_tmp_): If the rm -rf fails, wait a second
and try again.  This works around a problem I observed on Solaris
10 on a circa 2001 Sun Fire 280R with a single 750 MHz UltraSPARC
III, where a subprocess had not yet exited by the time the test
script attempted to remove the subprocess’s working directory.
This can happen, for example, if the process A in the shell
command ‘A | B’ closes stdout, checks that the close succeeded
-- a necessary check if stdout is NFS, on Solaris anyway --
and uses that check to affect its exit status.
In this situation, B can read end-of-file from its standard input
and exit before A exits, and then the shell, which waits only for B,
can then attempt to remove A’s working directory during cleanup.
This is not a problem on GNU/Linux where one can remove a
process’s working directory, but it is a problem on Solaris 10
which does not allow this.  POSIX allows the Solaris 10 behavior.
---
 ChangeLog     | 19 +++++++++++++++++++
 tests/init.sh |  7 +++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 286a53caae..feb005dfbe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2025-09-21  Paul Eggert  <egg...@cs.ucla.edu>
+
+       tests: avoid test failure due to rmdir race
+       * tests/init.sh (remove_tmp_): If the rm -rf fails, wait a second
+       and try again.  This works around a problem I observed on Solaris
+       10 on a circa 2001 Sun Fire 280R with a single 750 MHz UltraSPARC
+       III, where a subprocess had not yet exited by the time the test
+       script attempted to remove the subprocess’s working directory.
+       This can happen, for example, if the process A in the shell
+       command ‘A | B’ closes stdout, checks that the close succeeded
+       -- a necessary check if stdout is NFS, on Solaris anyway --
+       and uses that check to affect its exit status.
+       In this situation, B can read end-of-file from its standard input
+       and exit before A exits, and then the shell, which waits only for B,
+       can then attempt to remove A’s working directory during cleanup.
+       This is not a problem on GNU/Linux where one can remove a
+       process’s working directory, but it is a problem on Solaris 10
+       which does not allow this.  POSIX allows the Solaris 10 behavior.
+
 2025-09-21  Bruno Haible  <br...@clisp.org>
 
        doc: Update for Android API level 37.
diff --git a/tests/init.sh b/tests/init.sh
index 6a63f05ee9..1c81eb7537 100644
--- a/tests/init.sh
+++ b/tests/init.sh
@@ -484,8 +484,11 @@ remove_tmp_ ()
     # cd out of the directory we're about to remove
     cd "$initial_cwd_" || cd / || cd /tmp
     chmod -R u+rwx "$test_dir_"
-    # If removal fails and exit status was to be 0, then change it to 1.
-    rm -rf "$test_dir_" || { test $__st = 0 && __st=1; }
+    # If the first removal fails, wait for subprocesses to exit and try again.
+    # If that fails and exit status was to be 0, change it to 1.
+    rm -rf "$test_dir_" 2>/dev/null \
+      || { sleep 1 && rm -rf "$test_dir_"; } \
+      || { test $__st = 0 && __st=1; }
   fi
   exit $__st
 }
-- 
2.48.1


Reply via email to