Skip to content

Commit f07fcf2

Browse files
FrassleKevinRansom
authored andcommitted
Fix #7564 (#7596)
* Add a bind to Parallel test to force async continuations * Fixing Parallel and more tests * Use trampoline holder directly * Split race test to check with and without max degree * Fix RaceBetweenCancellationAndError tests (use an async that errors)
1 parent e8b20b0 commit f07fcf2

File tree

2 files changed

+26
-27
lines changed

2 files changed

+26
-27
lines changed

src/fsharp/FSharp.Core/async.fs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,31 +1250,28 @@ namespace Microsoft.FSharp.Control
12501250
|> unfake)
12511251
| Some maxDegreeOfParallelism ->
12521252
let mutable i = -1
1253-
let worker = MakeAsync (fun _ ->
1254-
while i < tasks.Length do
1253+
let rec worker (trampolineHolder : TrampolineHolder) =
1254+
if i < tasks.Length then
12551255
let j = Interlocked.Increment &i
12561256
if j < tasks.Length then
1257-
let trampolineHolder = new TrampolineHolder()
1258-
trampolineHolder.ExecuteWithTrampoline (fun () ->
1259-
let ctxt =
1257+
if innerCTS.Token.IsCancellationRequested then
1258+
let cexn = new OperationCanceledException (innerCTS.Token)
1259+
recordFailure (Choice2Of2 cexn) |> unfake
1260+
worker trampolineHolder |> unfake
1261+
else
1262+
let taskCtxt =
12601263
AsyncActivation.Create
12611264
innerCTS.Token
12621265
trampolineHolder
1263-
(fun res -> recordSuccess j res)
1264-
(fun edi -> recordFailure (Choice1Of2 edi))
1265-
(fun cexn -> recordFailure (Choice2Of2 cexn))
1266-
tasks.[j].Invoke ctxt
1267-
)
1268-
|> unfake
1266+
(fun res -> recordSuccess j res |> unfake; worker trampolineHolder)
1267+
(fun edi -> recordFailure (Choice1Of2 edi) |> unfake; worker trampolineHolder)
1268+
(fun cexn -> recordFailure (Choice2Of2 cexn) |> unfake; worker trampolineHolder)
1269+
tasks.[j].Invoke taskCtxt |> unfake
12691270
fake()
1270-
)
12711271
for x = 1 to maxDegreeOfParallelism do
1272-
QueueAsync
1273-
innerCTS.Token
1274-
(fun _ -> fake())
1275-
(fun edi -> recordFailure (Choice1Of2 edi))
1276-
(fun cexn -> recordFailure (Choice2Of2 cexn))
1277-
worker
1272+
let trampolineHolder = new TrampolineHolder()
1273+
trampolineHolder.QueueWorkItemWithTrampoline (fun () ->
1274+
worker trampolineHolder)
12781275
|> unfake
12791276

12801277
fake()))

tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ type AsyncModule() =
630630
member this.``Parallel with maxDegreeOfParallelism`` () =
631631
let mutable i = 1
632632
let action j = async {
633+
do! Async.Sleep 1
633634
Assert.AreEqual(j, i)
634635
i <- i + 1
635636
}
@@ -662,14 +663,17 @@ type AsyncModule() =
662663
Assert.AreEqual("maxDegreeOfParallelism", exc.ParamName)
663664
Assert.True(exc.Message.Contains("maxDegreeOfParallelism must be positive, was -1"))
664665

665-
// This has been failing very regularly on LINUX --- issue : https://github.com/dotnet/fsharp/issues/7112
666-
#if !TESTING_ON_LINUX
667666
[<Test>]
668-
member this.``RaceBetweenCancellationAndError.Parallel``() =
669-
[| for i in 1 .. 1000 -> async { return i } |]
667+
member this.``RaceBetweenCancellationAndError.Parallel(maxDegreeOfParallelism)``() =
668+
[| for i in 1 .. 1000 -> async { failwith "boom" } |]
670669
|> fun cs -> Async.Parallel(cs, 1)
670+
|> testErrorAndCancelRace "RaceBetweenCancellationAndError.Parallel(maxDegreeOfParallelism)"
671+
672+
[<Test>]
673+
member this.``RaceBetweenCancellationAndError.Parallel``() =
674+
[| for i in 1 .. 1000 -> async { failwith "boom" } |]
675+
|> fun cs -> Async.Parallel(cs)
671676
|> testErrorAndCancelRace "RaceBetweenCancellationAndError.Parallel"
672-
#endif
673677

674678
[<Test>]
675679
member this.``error on one workflow should cancel all others with maxDegreeOfParallelism``() =
@@ -679,13 +683,11 @@ type AsyncModule() =
679683
let job i = async {
680684
if i = 55 then failwith "boom"
681685
else
682-
do! Async.Sleep 1000
683686
incr counter
684687
}
685688

686-
let! _ = Async.Parallel ([ for i in 1 .. 100 -> job i ], 2) |> Async.Catch
687-
do! Async.Sleep 5000
689+
let! _ = Async.Parallel ([ for i in 1 .. 100 -> job i ], 1) |> Async.Catch
688690
return !counter
689691
} |> Async.RunSynchronously
690692

691-
Assert.AreEqual(0, counter)
693+
Assert.AreEqual(54, counter)

0 commit comments

Comments
 (0)