Skip to content

Commit 5e7d3eb

Browse files
authored
Merge pull request DeusData#1224 from DeusData/fix/daemon-app-tsan-wait-budget
test: size the daemon-application wait budget for TSan's slowdown tail
2 parents 5a5ed51 + e06d1b5 commit 5e7d3eb

3 files changed

Lines changed: 51 additions & 9 deletions

File tree

‎scripts/run-tests-parallel.sh‎

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,32 @@ mkdir -p "$LOGDIR"
4848
# setup. Two idempotent steps: protect the DIRECTORY (inheritance flags are
4949
# directory-only — a /T re-root leaves files with empty deny-all DACLs),
5050
# then /reset the children to re-inherit the clean set.
51-
case "$(uname -s 2>/dev/null)" in
52-
MINGW* | MSYS*)
51+
stamp_windows_build_dir() {
52+
local when="$1"
53+
case "$(uname -s 2>/dev/null)" in
54+
MINGW* | MSYS*) ;;
55+
*) return 0 ;;
56+
esac
57+
local runner_dir_w me stamp_out reset_out
5358
runner_dir_w="$(cygpath -w "$(dirname "$RUNNER")")"
5459
me="$(whoami | tr -d '\r')"
55-
MSYS2_ARG_CONV_EXCL='*' icacls "$runner_dir_w" /inheritance:r \
60+
stamp_out=$(MSYS2_ARG_CONV_EXCL='*' icacls "$runner_dir_w" /inheritance:r \
5661
/grant:r "${me}:(OI)(CI)F" '*S-1-5-18:(OI)(CI)F' '*S-1-5-32-544:(OI)(CI)F' \
57-
/Q >/dev/null 2>&1 || true
58-
MSYS2_ARG_CONV_EXCL='*' icacls "${runner_dir_w}\\*" /reset /T /C /Q >/dev/null 2>&1 || true
59-
;;
60-
esac
62+
/Q 2>&1) || echo "WARN: build-dir DACL stamp ($when) failed (user=$me dir=$runner_dir_w): $stamp_out"
63+
reset_out=$(MSYS2_ARG_CONV_EXCL='*' icacls "${runner_dir_w}\\*" /reset /T /C /Q 2>&1) ||
64+
echo "WARN: build-dir child DACL reset ($when) failed: $(printf '%s' "$reset_out" | tail -2)"
65+
# The stamp is load-bearing for the install-flow suites: verify it and say
66+
# so, in either direction — a silent stamp once cost a full CI round to
67+
# even see WHETHER it had run.
68+
if MSYS2_ARG_CONV_EXCL='*' icacls "$runner_dir_w" 2>/dev/null |
69+
grep -qE 'Authenticated Users|CREATOR OWNER'; then
70+
echo "WARN: build-dir DACL still grants cross-account mutation after $when stamp:"
71+
MSYS2_ARG_CONV_EXCL='*' icacls "$runner_dir_w" 2>&1 | head -8
72+
else
73+
echo "build-dir DACL stamped clean ($when, $runner_dir_w, user=$me)"
74+
fi
75+
}
76+
stamp_windows_build_dir pre-wave
6177

6278
SUITES_FILE="$LOGDIR/suites.txt"
6379
RESULTS_FILE="$LOGDIR/results.txt"
@@ -232,6 +248,13 @@ while IFS= read -r sname; do
232248
echo "$sname" >> "$FLEX_FILE"
233249
fi
234250
done < "$SER_FILE"
251+
# Wave suites spawn Cygwin-family tooling that can rewrite the build
252+
# directory's DACL behind the first stamp (observed: an arm shard whose
253+
# tail held the install-flow suites failed the source-directory policy
254+
# minutes after a clean pre-wave stamp, while its sibling shard passed).
255+
# Re-stamp at the tail boundary so the deadline-sensitive tail — which
256+
# hosts those suites — always starts from the verified-clean shape.
257+
stamp_windows_build_dir pre-tail
235258
xargs -P "${CBM_TAIL_JOBS:-2}" -I{} bash -c 'run_one "$@"' _ {} < "$FLEX_FILE"
236259
while IFS= read -r sname; do
237260
run_one "$sname"

‎src/daemon/service.c‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,12 +856,26 @@ static bool windows_private_file_prepare(const char *directory, const char *base
856856
* to the ~16 ms timer granularity, and a permanently obstructed path
857857
* (e.g. a directory squatting on it) must fail fast — a rejected client
858858
* is waiting behind this on the hello path with its own timeout. */
859-
ULONGLONG deadline = GetTickCount64() + 250;
859+
ULONGLONG obstruction_deadline = GetTickCount64() + 250;
860+
/* Genuine share collisions get a wider budget than obstruction: with
861+
* many concurrent appenders on a loaded, sanitized CI runner the
862+
* last-in-line writer can legitimately spend more than 250 ms behind
863+
* its peers' brief exclusive windows, and the no-drop contract for
864+
* conflict events outranks latency there — while a permanently
865+
* obstructed path (a directory squatting on the name) still fails
866+
* inside 250 ms, because a rejected client is waiting behind this on
867+
* the hello path with its own timeout. */
868+
ULONGLONG contention_deadline = GetTickCount64() + 2000;
860869
for (;;) {
870+
SetLastError(ERROR_SUCCESS);
861871
FILE *file = cbm_daemon_ipc_private_log_open(directory, base, SIZE_MAX);
862872
if (file) {
863873
return fclose(file) == 0;
864874
}
875+
DWORD open_error = GetLastError();
876+
bool transient_collision =
877+
open_error == ERROR_SHARING_VIOLATION || open_error == ERROR_LOCK_VIOLATION;
878+
ULONGLONG deadline = transient_collision ? contention_deadline : obstruction_deadline;
865879
if (GetTickCount64() >= deadline) {
866880
return false;
867881
}

‎tests/test_daemon_application.c‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@
2727
#include <stdlib.h>
2828
#include <string.h>
2929

30-
enum { APP_TEST_TIMEOUT_MS = 2000, APP_TEST_PATH_CAP = 1024 };
30+
/* Observation-wait budget. This is a HANG DETECTOR, not a latency
31+
* assertion: every waiter returns the moment its condition holds, so green
32+
* runs never pay it. It must absorb ThreadSanitizer's 5-20x slowdown on a
33+
* loaded 3-core CI runner — at 2000 ms the cancel-delivery wait lost the
34+
* tail of that distribution once in seven otherwise-green TSan rounds. */
35+
enum { APP_TEST_TIMEOUT_MS = 10000, APP_TEST_PATH_CAP = 1024 };
3136

3237
typedef struct {
3338
char runtime_parent[APP_TEST_PATH_CAP];

0 commit comments

Comments
 (0)