Skip to content

Commit 6a933f6

Browse files
majochaT-Gro
andauthored
Fix Post on disposed mailbox (#17849) (#17922)
* nullify disposed waithandle * add test * rns --------- Co-authored-by: Tomas Grosup <[email protected]>
1 parent d566f53 commit 6a933f6

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
### Fixed
2+
3+
* Fix exception on Post after MailboxProcessor was disposed ([Issue #17849](https://github.com/dotnet/fsharp/issues/17849), [PR #17922](https://github.com/dotnet/fsharp/pull/17922))
4+
5+
### Added
6+
7+
### Changed
8+
9+
### Breaking Changes

src/FSharp.Core/mailbox.fs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,11 @@ type Mailbox<'Msg>(cancellationSupported: bool, isThrowExceptionAfterDisposed: b
340340
inboxStore.Clear()
341341

342342
arrivals.Clear()
343-
isDisposed <- true)
343+
isDisposed <- true
344344

345-
if isNotNull pulse then
346-
(pulse :> IDisposable).Dispose()
345+
if isNotNull pulse then
346+
(pulse :> IDisposable).Dispose()
347+
pulse <- null)
347348

348349
#if DEBUG
349350
member x.UnsafeContents = (x.inbox, arrivals, pulse, savedCont) |> box

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,3 +557,42 @@ module MailboxProcessorType =
557557
}
558558

559559
Assert.True(iteration.Result > 1, "TryScan did not timeout")
560+
561+
let ordered() =
562+
let mutable current = 1
563+
fun n ->
564+
if n < current then failwith $"step {n} already happened"
565+
SpinWait.SpinUntil(fun () -> n = current)
566+
current <- n + 1
567+
568+
// See https://github.com/dotnet/fsharp/issues/17849
569+
[<Fact>]
570+
let ``Disposed MailboxProcessor does not throw on Post`` () =
571+
task {
572+
let step = ordered()
573+
574+
let cts = new CancellationTokenSource()
575+
let mb =
576+
MailboxProcessor.Start( (fun inbox ->
577+
async {
578+
step 1
579+
do! inbox.Receive()
580+
do! inbox.Receive()
581+
return ()
582+
}),
583+
cancellationToken = cts.Token
584+
)
585+
586+
step 2
587+
// ensure pulse gets created
588+
do! Task.Delay 100
589+
mb.Post()
590+
591+
mb.Dispose()
592+
593+
do! Task.Delay 100
594+
595+
mb.Post()
596+
597+
cts.Cancel()
598+
}

0 commit comments

Comments
 (0)