Skip to content

Commit 26372fa

Browse files
ararslanKeno
andauthored
Try to close race condition in FileWatching tests (#38407) (#39978)
* Try to close race condition in FreeBSD tests We're seeing frequent test failures in the FileWatching test on FreeBSD. Here's my theory of what happens: - Both the timer callback and the poll callback execute on the same libuv loop - They each schedule their respective tasks - Whichever task gets scheduled first first determines the result However, in the test, we expect that, if the poll callback ran, (which we know because we know there was an event pending), then that result does actually get delivered to the toplevel task. This PR tries to close this hole by adding the following condition: If the task is no longer waiting on the file watcher (because libuv already scheduled it), then wait for the task to run to completion, independent of any timeout. I believe this should close the above race condition and hopefully fix the test. * Add another super-short timeout to try to trigger the same-tick issue (cherry picked from commit 9a8a675) Co-authored-by: Keno Fischer <keno@juliacomputing.com>
1 parent fe2311a commit 26372fa

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

stdlib/FileWatching/src/FileWatching.jl

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ mutable struct _FDWatcher
254254
end
255255
end
256256

257+
function iswaiting(fwd::_FDWatcher, t::Task)
258+
return fwd.notify.waitq === t.queue
259+
end
260+
257261
mutable struct FDWatcher
258262
watcher::_FDWatcher
259263
readable::Bool
@@ -653,10 +657,10 @@ function poll_fd(s::Union{RawFD, Sys.iswindows() ? WindowsRawSocket : Union{}},
653657
try
654658
if timeout_s >= 0
655659
result::FDEvent = FDEvent()
656-
timer = Timer(timeout_s) do t
657-
notify(wt)
658-
end
659-
@async begin
660+
t = @async begin
661+
timer = Timer(timeout_s) do t
662+
notify(wt)
663+
end
660664
try
661665
result = wait(fdw, readable=readable, writable=writable)
662666
catch e
@@ -666,6 +670,12 @@ function poll_fd(s::Union{RawFD, Sys.iswindows() ? WindowsRawSocket : Union{}},
666670
notify(wt)
667671
end
668672
wait(wt)
673+
# It's possible that both the timer and the poll fired on the same
674+
# libuv loop. In that case, which event we see here first depends
675+
# on task schedule order. If we can see that the task isn't waiting
676+
# on the file watcher anymore, just let it finish so we can see
677+
# the modification to `result`
678+
iswaiting(fdw, t) || wait(t)
669679
return result
670680
else
671681
return wait(fdw, readable=readable, writable=writable)

stdlib/FileWatching/test/runtests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ using Base: uv_error, Experimental
1212
# Writable ends are always tested for write-ability before a write
1313

1414
n = 20
15-
intvls = [2, .2, .1, .005]
15+
intvls = [2, .2, .1, .005, .00001]
1616

1717
pipe_fds = fill((Base.INVALID_OS_HANDLE, Base.INVALID_OS_HANDLE), n)
1818
for i in 1:n

0 commit comments

Comments
 (0)