Roll forward of https://github.com/bazelbuild/bazel/commit/3904ac33a983fd8faebba1b52bcac5a3ff942029 (https://github.com/bazelbuild/bazel/commit/3904ac33a983fd8faebba1b52bcac5a3ff942029). Fix #4625 by running the test process in a sub-shell.

Apparently, nested background processes interfere with SIGINT handling in bash. I don't 100% understand why and how, but I do have a small bash script that demonstrates the problem: script A that spawns a background process, sends it a SIGINT, and verifies it was received. The script works, *unless* run in the background by a process B; this extra layer of backgrounding cause process A's logic to stop working. See experimental/users/olaola/shell/ for examples. See also https://stackoverflow.com/questions/48847722/nested-background-processes-and-sigint-handling

*** Original change description ***

Fixing test-setup.sh occasionally missing stdout/stderr, on systems where "tail --pid" is supported.

The solutions aren't mine, the new test was taken from Ola's unknown commit and the way to avoid race condition courtesy of sethkoehler@

Mitigates #4608 for compatible Linux systems.

TESTED=presubmits, manual shell tests on new bazel
RELNOTES: None
PiperOrigin-RevId: 186312008
diff --git a/src/test/shell/bazel/bazel_test_test.sh b/src/test/shell/bazel/bazel_test_test.sh
index 944c08f..389bc91 100755
--- a/src/test/shell/bazel/bazel_test_test.sh
+++ b/src/test/shell/bazel/bazel_test_test.sh
@@ -339,6 +339,41 @@
 \?\?\?\?\?<!CDATA\[\]\]>\]\]<!\[CDATA\[>\]\]></system-out>'
 }
 
+# Tests that the test.xml and test.log are correct and the test does not
+# hang when the test launches a subprocess.
+function test_subprocess_non_timeout() {
+  mkdir -p dir
+
+  cat <<'EOF' > dir/test.sh
+echo "Pretending to sleep..."
+sleep 600 &
+echo "Finished!" >&2
+exit 0
+EOF
+
+  chmod +x dir/test.sh
+
+  cat <<'EOF' > dir/BUILD
+  sh_test(
+    name = "test",
+    timeout = "short",
+    srcs = [ "test.sh" ],
+  )
+EOF
+
+  bazel test --test_output=streamed --test_timeout=2 \
+     //dir:test &> $TEST_log || fail "expected success"
+
+  xml_log=bazel-testlogs/dir/test/test.xml
+  expect_log 'Pretending to sleep...'
+  expect_log 'Finished!'
+  [ -s "${xml_log}" ] || fail "${xml_log} was not present after test"
+  cp "${xml_log}" $TEST_log
+  expect_log_once "testcase"
+  expect_log 'Pretending to sleep...'
+  expect_log 'Finished!'
+}
+
 # Check that fallback xml output is correctly generated for sharded tests.
 function test_xml_fallback_for_sharded_test() {
   mkdir -p dir
diff --git a/tools/test/test-setup.sh b/tools/test/test-setup.sh
index aa6f722..002edb8 100755
--- a/tools/test/test-setup.sh
+++ b/tools/test/test-setup.sh
@@ -218,10 +218,30 @@
 done
 start=$(date +%s)
 
-if [ -z "$COVERAGE_DIR" ]; then
-  "${TEST_PATH}" "$@" 2> >(tee -a "${XML_OUTPUT_FILE}.log" >&2) 1> >(tee -a "${XML_OUTPUT_FILE}.log") 2>&1 || exitCode=$?
+# Check if we have tail --pid option
+dummy=1 &
+pid=$!
+has_tail=true
+tail -fq --pid $pid -s 0.001 /dev/null &> /dev/null || has_tail=false
+
+if [ "$has_tail" == true ] && [  -z "$no_echo" ]; then
+  touch "${XML_OUTPUT_FILE}.log"
+  if [ -z "$COVERAGE_DIR" ]; then
+    ("${TEST_PATH}" "$@" &>"${XML_OUTPUT_FILE}.log") &
+    pid=$!
+  else
+    ("$1" "$TEST_PATH" "${@:3}" &> "${XML_OUTPUT_FILE}.log") &
+    pid=$!
+  fi
+  tail -fq --pid $pid -s 0.001 "${XML_OUTPUT_FILE}.log"
+  wait $pid
+  exitCode=$?
 else
-  "$1" "$TEST_PATH" "${@:3}" 2> >(tee -a "${XML_OUTPUT_FILE}.log" >&2) 1> >(tee -a "${XML_OUTPUT_FILE}.log") 2>&1 || exitCode=$?
+  if [ -z "$COVERAGE_DIR" ]; then
+    "${TEST_PATH}" "$@" 2> >(tee -a "${XML_OUTPUT_FILE}.log" >&2) 1> >(tee -a "${XML_OUTPUT_FILE}.log") 2>&1 || exitCode=$?
+  else
+    "$1" "$TEST_PATH" "${@:3}" 2> >(tee -a "${XML_OUTPUT_FILE}.log" >&2) 1> >(tee -a "${XML_OUTPUT_FILE}.log") 2>&1 || exitCode=$?
+  fi
 fi
 
 for signal in $signals; do