Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Locate exceptions thrown by Microsoft.FSharp.Control.Trampoline

I am responsible for an F# WPF application. It emails me when an unhandled exception occurs. Most of the time, I'm able to identify the source of the exception from the error message and stack trace. However, I occasionally get a message like the following, which does not include any of my code in the stack trace.

Summary:
Object reference not set to an instance of an object.
--------------
Details:

System.NullReferenceException: 
Object reference not set to an instance of an object.
   at Microsoft.FSharp.Control.CancellationTokenOps.Start@1234-1.Invoke(Exception e)
   at <StartupCode$FSharp-Core>.$Control.loop@435-40(Trampoline this, FSharpFunc`2 action)
   at Microsoft.FSharp.Control.Trampoline.ExecuteAction(FSharpFunc`2 firstAction)
   at Microsoft.FSharp.Control.TrampolineHolder.Protect(FSharpFunc`2 firstAction)
   at <StartupCode$FSharp-Core>[email protected](Object state)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

What clues are available in this stack trace that might help me identify the source of this exception?

For example, I'm assuming the original exception is being thrown within an async computation. (The majority of my async code is based on F# async blocks.) Could my NullReferenceException have occurred anywhere in an async block? I notice that the exception occurred within a Start() method. Or is it? That Start() method takes an Exception instance so perhaps the exception was thrown before that. Does that tell me anything? I wonder if someone is familiar enough with the Microsoft.FSharp.Control.Trampoline to point me in the right direction.

By the way, in my error handling code, I am careful about checking all the InnerExceptions and handling AggregateExceptions. So I think this is all the information available in the Exception instance, but I could be wrong.

like image 836
Wallace Kelly Avatar asked Feb 12 '16 17:02

Wallace Kelly


1 Answers

I did a quick test. The following Console program generates the identical stack trace.

[<EntryPoint>]
let main argv = 

    async { printfn "Inside async block."
            let o = null
            o.GetType() |> ignore
    } |> Async.Start

    System.Console.ReadKey(true) |> ignore
    0 // return an integer exit code

That tells me the following:

  1. The mystery exception is happening within an async block.
  2. It could occur anywhere in the async block.
  3. The only way to diagnose is to improve the error handling around async blocks (perhaps with Async.Catch) and redeploy a new version of the application and wait for it to happen again.
like image 150
Wallace Kelly Avatar answered Nov 10 '22 17:11

Wallace Kelly