MailboxProcessor and exceptions
f#, mailboxprocessor
Solution
I think the reason why the `MailboxProcessor` in F# does not contain any mechanism for handling exceptions is that it is not clear what is the best way for doing that. For example, you may want to have a global event that is triggered when an unhandled exception happens, but you may want to rethrow the exception on the next call to `Post` or `PostAndReply`.
Both of the options can be implemented based on the standard `MailboxProcessor`, so it is possible to add the behaviour you want. For example, the following snippet shows `HandlingMailbox` that adds a global exception handler. It has the same interface as normal `MailboxProcessor` (I omitted some methods), but it adds `OnError` event that is triggered when an exception happens:
type HandlingMailbox<'T> private(f:HandlingMailbox<'T> -> Async<unit>) as self =
let event = Event<_>()
let inbox = new MailboxProcessor<_>(fun inbox -> async {
try
return! f self
with e ->
event.Trigger(e) })
member x.OnError = event.Publish
member x.Start() = inbox.Start()
member x.Receive() = inbox.Receive()
member x.Post(v:'T) = inbox.Post(v)
static member Start(f) =
let mbox = new HandlingMailbox<_>(f)
mbox.Start()
mbox
To use it, you would write the same code as what you wrote before, but you can now handle exceptions asynchronously:
let counter = HandlingMailbox<_>.Start(fun inbox -> async {
while true do
printfn "waiting for data..."
let! data = inbox.Receive()
failwith "fail" })
counter.OnError.Add(printfn "Exception: %A")
counter.Post(42)
Problem
I wonder, why `MailboxProcessor`'s default strategy of handling exceptions is just silently ignore them. For example: ``` let counter = MailboxProcessor.Start(fun inbox -> let rec loop() = async { printfn "waiting for data..." let! data = inbox.Receive() failwith "fail" // simulate throwing of an exception printfn "Got: %d" data return! loop() } loop ()) () counter.Post(42) counter.Post(43) counter.Post(44) Async.Sleep 1000 |> Async.RunSynchronously ``` and nothing happens. There is no fatal stop of the program execution, or message box with "An unhandled exception" arises. Nothing. This situation becomes worse if someone uses `PostAndReply` method: a guaranteed deadlock as the result. Any reasons for such behavior?