Skip to content

Commit 899d210

Browse files
Frasslebaronfel
authored andcommitted
Fix LinkedSubSource leak in Async.Choice (#7892)
* Fix LinkedSubSource leak in Async.Choice * ref -> mutable
1 parent 9f7f2e5 commit 899d210

File tree

1 file changed

+38
-19
lines changed

1 file changed

+38
-19
lines changed

src/fsharp/FSharp.Core/async.fs

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,35 +1293,54 @@ namespace Microsoft.FSharp.Control
12931293
| Choice1Of2 computations ->
12941294
ProtectedCode ctxt (fun ctxt ->
12951295
let ctxtWithSync = DelimitSyncContext ctxt
1296-
let noneCount = ref 0
1297-
let exnCount = ref 0
1296+
let mutable count = computations.Length
1297+
let mutable noneCount = 0
1298+
let mutable someOrExnCount = 0
12981299
let innerCts = new LinkedSubSource(ctxtWithSync.token)
12991300

13001301
let scont (result: 'T option) =
1301-
match result with
1302-
| Some _ ->
1303-
if Interlocked.Increment exnCount = 1 then
1304-
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont result)
1302+
let result =
1303+
match result with
1304+
| Some _ ->
1305+
if Interlocked.Increment &someOrExnCount = 1 then
1306+
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont result)
1307+
else
1308+
fake()
1309+
1310+
| None ->
1311+
if Interlocked.Increment &noneCount = computations.Length then
1312+
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont None)
1313+
else
1314+
fake()
1315+
1316+
if Interlocked.Decrement &count = 0 then
1317+
innerCts.Dispose()
1318+
1319+
result
1320+
1321+
let econt (exn: ExceptionDispatchInfo) =
1322+
let result =
1323+
if Interlocked.Increment &someOrExnCount = 1 then
1324+
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.econt exn)
13051325
else
13061326
fake()
13071327

1308-
| None ->
1309-
if Interlocked.Increment noneCount = computations.Length then
1310-
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.cont None)
1328+
if Interlocked.Decrement &count = 0 then
1329+
innerCts.Dispose()
1330+
1331+
result
1332+
1333+
let ccont (exn: OperationCanceledException) =
1334+
let result =
1335+
if Interlocked.Increment &someOrExnCount = 1 then
1336+
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.ccont exn)
13111337
else
13121338
fake()
13131339

1314-
let econt (exn: ExceptionDispatchInfo) =
1315-
if Interlocked.Increment exnCount = 1 then
1316-
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.econt exn)
1317-
else
1318-
fake()
1340+
if Interlocked.Decrement &count = 0 then
1341+
innerCts.Dispose()
13191342

1320-
let ccont (exn: OperationCanceledException) =
1321-
if Interlocked.Increment exnCount = 1 then
1322-
innerCts.Cancel(); ctxtWithSync.trampolineHolder.ExecuteWithTrampoline (fun () -> ctxtWithSync.ccont exn)
1323-
else
1324-
fake()
1343+
result
13251344

13261345
for c in computations do
13271346
QueueAsync innerCts.Token scont econt ccont c |> unfake

0 commit comments

Comments
 (0)