Skip to content

Commit 7241bc1

Browse files
ptarjangitster
authored andcommitted
fsmonitor: add tests for Linux
Add a smoke test that verifies the filesystem actually delivers inotify events to the daemon. On some configurations (e.g., overlayfs with older kernels), inotify watches succeed but events are never delivered. The daemon cookie wait will time out, but every subsequent test would fail. Skip the entire test file early when this is detected. Add a test that exercises rapid nested directory creation to verify the daemon correctly handles the EEXIST race between recursive scan and queued inotify events. When IN_MASK_CREATE is available and a directory watch is added during recursive registration, the kernel may also deliver a queued IN_CREATE event for the same directory. The second inotify_add_watch() returns EEXIST, which must be treated as harmless. An earlier version of the listener crashed in this scenario. Reduce --start-timeout from the default 60 seconds to 10 seconds so that tests fail promptly when the daemon cannot start. Harden the test helpers to work in environments without procps (e.g., Fedora CI): fall back to reading /proc/$pid/stat for the process group ID when ps is unavailable, guard stop_git() against an empty pgid, and redirect stderr from kill to /dev/null to avoid noise when processes have already exited. Use set -m to enable job control in the submodule-pull test so that the background git pull gets its own process group, preventing the shell wait from blocking on the daemon. setsid() in the previous commit detaches the daemon itself, but the intermediate git pull process still needs its own process group for the test shell to manage it correctly. Signed-off-by: Paul Tarjan <github@paulisageek.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 485d621 commit 7241bc1

File tree

1 file changed

+82
-7
lines changed

1 file changed

+82
-7
lines changed

t/t7527-builtin-fsmonitor.sh

Lines changed: 82 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,58 @@ then
1010
test_done
1111
fi
1212

13+
# Verify that the filesystem delivers events to the daemon.
14+
# On some configurations (e.g., overlayfs with older kernels),
15+
# inotify watches succeed but events are never delivered. The
16+
# cookie wait will time out and the daemon logs a trace message.
17+
#
18+
# Use "timeout" (if available) to guard each step against hangs.
19+
maybe_timeout () {
20+
if type timeout >/dev/null 2>&1
21+
then
22+
timeout "$@"
23+
else
24+
shift
25+
"$@"
26+
fi
27+
}
28+
verify_fsmonitor_works () {
29+
git init test_fsmonitor_smoke || return 1
30+
31+
GIT_TRACE_FSMONITOR="$PWD/smoke.trace" &&
32+
export GIT_TRACE_FSMONITOR &&
33+
maybe_timeout 30 \
34+
git -C test_fsmonitor_smoke fsmonitor--daemon start \
35+
--start-timeout=10
36+
ret=$?
37+
unset GIT_TRACE_FSMONITOR
38+
if test $ret -ne 0
39+
then
40+
rm -rf test_fsmonitor_smoke smoke.trace
41+
return 1
42+
fi
43+
44+
maybe_timeout 10 \
45+
test-tool -C test_fsmonitor_smoke fsmonitor-client query \
46+
--token 0 >/dev/null 2>&1
47+
maybe_timeout 5 \
48+
git -C test_fsmonitor_smoke fsmonitor--daemon stop 2>/dev/null
49+
! grep -q "cookie_wait timed out" "$PWD/smoke.trace" 2>/dev/null
50+
ret=$?
51+
rm -rf test_fsmonitor_smoke smoke.trace
52+
return $ret
53+
}
54+
55+
if ! verify_fsmonitor_works
56+
then
57+
skip_all="filesystem does not deliver fsmonitor events (container/overlayfs?)"
58+
test_done
59+
fi
60+
1361
stop_daemon_delete_repo () {
1462
r=$1 &&
15-
test_might_fail git -C $r fsmonitor--daemon stop &&
63+
test_might_fail maybe_timeout 30 \
64+
git -C $r fsmonitor--daemon stop 2>/dev/null
1665
rm -rf $1
1766
}
1867

@@ -67,7 +116,7 @@ start_daemon () {
67116
export GIT_TEST_FSMONITOR_TOKEN
68117
fi &&
69118

70-
git $r fsmonitor--daemon start &&
119+
git $r fsmonitor--daemon start --start-timeout=10 &&
71120
git $r fsmonitor--daemon status
72121
)
73122
}
@@ -520,6 +569,28 @@ test_expect_success 'directory changes to a file' '
520569
grep "^event: dir1$" .git/trace
521570
'
522571

572+
test_expect_success 'rapid nested directory creation' '
573+
test_when_finished "git fsmonitor--daemon stop; rm -rf rapid" &&
574+
575+
start_daemon --tf "$PWD/.git/trace" &&
576+
577+
# Rapidly create nested directories to exercise race conditions
578+
# where directory watches may be added concurrently during
579+
# event processing and recursive scanning.
580+
for i in $(test_seq 1 20)
581+
do
582+
mkdir -p "rapid/nested/dir$i/subdir/deep" || return 1
583+
done &&
584+
585+
# Give the daemon time to process all events
586+
sleep 1 &&
587+
588+
test-tool fsmonitor-client query --token 0 &&
589+
590+
# Verify daemon is still running (did not crash)
591+
git fsmonitor--daemon status
592+
'
593+
523594
# The next few test cases exercise the token-resync code. When filesystem
524595
# drops events (because of filesystem velocity or because the daemon isn't
525596
# polling fast enough), we need to discard the cached data (relative to the
@@ -910,7 +981,10 @@ test_expect_success "submodule absorbgitdirs implicitly starts daemon" '
910981
start_git_in_background () {
911982
git "$@" &
912983
git_pid=$!
913-
git_pgid=$(ps -o pgid= -p $git_pid)
984+
git_pgid=$(ps -o pgid= -p $git_pid 2>/dev/null ||
985+
awk '{print $5}' /proc/$git_pid/stat 2>/dev/null) &&
986+
git_pgid="${git_pgid## }" &&
987+
git_pgid="${git_pgid%% }"
914988
nr_tries_left=10
915989
while true
916990
do
@@ -921,15 +995,16 @@ start_git_in_background () {
921995
fi
922996
sleep 1
923997
nr_tries_left=$(($nr_tries_left - 1))
924-
done >/dev/null 2>&1 &
998+
done >/dev/null 2>&1 3>&- 4>&- 5>&- 6>&- 7>&- &
925999
watchdog_pid=$!
9261000
wait $git_pid
9271001
}
9281002

9291003
stop_git () {
930-
while kill -0 -- -$git_pgid
1004+
test -n "$git_pgid" || return 0
1005+
while kill -0 -- -$git_pgid 2>/dev/null
9311006
do
932-
kill -- -$git_pgid
1007+
kill -- -$git_pgid 2>/dev/null
9331008
sleep 1
9341009
done
9351010
}
@@ -944,7 +1019,7 @@ stop_watchdog () {
9441019

9451020
test_expect_success !MINGW "submodule implicitly starts daemon by pull" '
9461021
test_atexit "stop_watchdog" &&
947-
test_when_finished "stop_git; rm -rf cloned super sub" &&
1022+
test_when_finished "set +m; stop_git; rm -rf cloned super sub" &&
9481023
9491024
create_super super &&
9501025
create_sub sub &&

0 commit comments

Comments
 (0)