Skip to content

Async tests with cancellation are flaky #11586

@brettfo

Description

@brettfo

The following tests are flaky:

[<Fact>]
member this.``OnCancel.RaceBetweenCancellationHandlerAndDisposingHandlerRegistration``() =
let test() =
use flag = new ManualResetEvent(false)
use cancelHandlerRegistered = new ManualResetEvent(false)
let cts = new System.Threading.CancellationTokenSource()
let go = async {
use! holder = Async.OnCancel(fun() -> lock flag (fun() -> flag.Set()) |> ignore)
let _ = cancelHandlerRegistered.Set()
while true do
do! Async.Sleep 50
}
Async.Start (go, cancellationToken = cts.Token)
//wait until we are sure the Async.OnCancel has run:
Assert.True(cancelHandlerRegistered.WaitOne(TimeSpan.FromSeconds 5.))
//now cancel:
cts.Cancel()
//cancel handler should have run:
Assert.True(flag.WaitOne(TimeSpan.FromSeconds 5.))
for _i = 1 to 300 do test()
[<Fact>]
member this.``OnCancel.RaceBetweenCancellationAndDispose``() =
let flag = ref 0
let cts = new System.Threading.CancellationTokenSource()
let go = async {
use disp =
cts.Cancel()
{ new IDisposable with
override _.Dispose() = incr flag }
while true do
do! Async.Sleep 50
}
try
Async.RunSynchronously (go, cancellationToken = cts.Token)
with
:? System.OperationCanceledException -> ()
Assert.AreEqual(1, !flag)
[<Fact>]
member this.``OnCancel.CancelThatWasSignalledBeforeRunningTheComputation``() =
let test() =
let cts = new System.Threading.CancellationTokenSource()
let go e (flag : bool ref) = async {
let! _ = Async.AwaitWaitHandle e
use! _holder = Async.OnCancel(fun () -> flag := true)
while true do
do! Async.Sleep 100
}
let evt = new System.Threading.ManualResetEvent(false)
let finish = new System.Threading.ManualResetEvent(false)
let cancelledWasCalled = ref false
Async.StartWithContinuations(go evt cancelledWasCalled, ignore, ignore, (fun _ -> finish.Set() |> ignore), cancellationToken = cts.Token)
evt.Set() |> ignore
cts.Cancel()
let ok = wait finish 3000
Assert.True(ok, "Computation should be completed")
Assert.False(!cancelledWasCalled, "Cancellation handler should not be called")
for _i = 1 to 3 do test()

The signed build can fail with stack traces that look like:

The active test run was aborted. Reason: Test host process crashed : go

Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.

   at [email protected](ExceptionDispatchInfo edi)
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in /Users/runner/work/1/s/src/fsharp/FSharp.Core/async.fs:line 104
   at Microsoft.FSharp.Control.AsyncPrimitives.continuation@951-2(AsyncActivation`1 ctxt, Boolean useCcontForTaskCancellation, Task completedTask) in /Users/runner/work/1/s/src/fsharp/FSharp.Core/async.fs:line 952
   at Microsoft.FSharp.Control.AsyncPrimitives.taskContinueWithUnit(Task task, AsyncActivation`1 ctxt, Boolean useCcontForTaskCancellation) in /Users/runner/work/1/s/src/fsharp/FSharp.Core/async.fs:line 966
   at <StartupCode$FSharp-Core>[email protected](AsyncActivation`1 ctxt) in /Users/runner/work/1/s/src/fsharp/FSharp.Core/async.fs:line 1708
   at Microsoft.FSharp.Control.AsyncPrimitives.ProtectedCode[T](AsyncActivation`1 ctxt, FSharpFunc`2 userCode) in /Users/runner/work/1/s/src/fsharp/FSharp.Core/async.fs:line 453
   at <StartupCode$FSharp-Core>[email protected](AsyncActivation`1 ctxt) in /Users/runner/work/1/s/src/fsharp/FSharp.Core/async.fs:line 1690
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction) in /Users/runner/work/1/s/src/fsharp/FSharp.Core/async.fs:line 104
   at <StartupCode$FSharp-Core>[email protected](Object o) in /Users/runner/work/1/s/src/fsharp/FSharp.Core/async.fs:line 157
   at System.Threading.ThreadPoolWorkQueue.Dispatch()

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions