Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Debugger should not break on f# (F sharp) exception in async blocks #5539

Open
vsfeedback opened this issue Aug 20, 2018 · 3 comments
Open
Labels
Area-Debug stepping, debug points, stacks and more Feature Improvement
Milestone

Comments

@vsfeedback
Copy link

vsfeedback commented Aug 20, 2018

The following code causes the debugger to break when the exception is thrown. Clearly the exception is handled and so the debugger should not break.

If I continue execution the program continues to run normally; printing "oops" on the screen as expected.

[<EntryPoint>]
let main argv =
    async {
        try
            do! Async.Sleep(1)
            failwith "oops" // The debugger breaks here but it should not as the exception is handled. It should behave like the C# version
        with
        | ex -> printfn "%s" (ex.Message)
    }
    |> Async.RunSynchronously

    Console.ReadLine() |> ignore
    0 

Compare this with the equivalent C# code. This does not break when the exception is thrown. The F# version should behave the same way and not break!

using System;
using System.Threading.Tasks;

namespace CSharpTaskException
{
    class Program
    {
        static void Main(string[] args)
        {
            async Task DoSomething()
            {
                try
                {
                    await Task.Delay(1);
                    throw new Exception(&quot;oops&quot;); // ****** This does not cause the debugger to break as the exception is handled
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }

            DoSomething().Wait();

            Console.ReadLine();
        }
    }
}

This issue has been moved from https://developercommunity.visualstudio.com/content/problem/314461/debugger-should-not-break-on-f-f-sharp-exception-i.html
VSTS ticketId: 666263

These are the original issue comments:
(no comments)
These are the original issue solutions:
(no solutions)

@cartermp cartermp added the Area-Debug stepping, debug points, stacks and more label Aug 20, 2018
@cartermp
Copy link
Contributor

I think this can be safely attributed to the host of different debugging issues with CE, especially async. But it's good to have it tracked.

@cartermp cartermp added the Area-Library Issues for FSharp.Core not covered elsewhere label Aug 20, 2018
@dsyme
Copy link
Contributor

dsyme commented Sep 13, 2018

Notes

  • This is related to Just-My-Code being on. If that is off, then the exception is not being reported as uncaught

  • The call stack is:

   at Program.main@8-2.Invoke(Unit _arg1)
   at Microsoft.FSharp.Control.AsyncPrimitives.CallThenInvokeNoHijackCheck[a,b](AsyncActivation`1 ctxt, FSharpFunc`2 userCode, b result1)
   at Microsoft.FSharp.Control.Trampoline.Execute(FSharpFunc`2 firstAction)
   at Microsoft.FSharp.Control.TrampolineHolder.ExecuteWithTrampoline(FSharpFunc`2 firstAction)
   at <StartupCode$FSharp-Core>.$Async.Sleep@1355-1.Invoke(Object _arg3)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.TimerQueueTimer.CallCallback()
   at System.Threading.TimerQueueTimer.Fire()
   at System.Threading.TimerQueue.FireNextTimers()
  • The Just My Code mechanism thinks the exception is escaping user code because it is not caught by any user code on the callstack before library code occurs

  • It is possible that annotating either user code or library code with other attributes will improve this. There is some information on Mike Stall's old blog and there is sure to be more information around too https://blogs.msdn.microsoft.com/jmstall/2004/12/31/how-can-i-debug-just-my-code/

  • It's possible inlining more async implementation into user code would help, though all control constructs would need to be inlined to ensure no library code remains on the stack

@dsyme
Copy link
Contributor

dsyme commented Sep 13, 2018

The other option is to inline move async/control code to become user code, specifically inlining

  • CallThenContinue
  • CallThenInvoke
  • CallThenInvokeNoHijackCheck
  • CallFilterThenInvoke
  • ProtectedCode

from async.fs. This would need an FSharp.Core update and a new entry point for unprotected, non-hijacked invocation of an async (effectively making the "Invoke" function on an async public via a backdoor). In the big picture that would be ok I think.

@cartermp cartermp added this to the Unknown milestone Sep 15, 2018
@dsyme dsyme removed the Area-Library Issues for FSharp.Core not covered elsewhere label Mar 30, 2022
@vzarytovskii vzarytovskii moved this to Not Planned in F# Compiler and Tooling Jun 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Debug stepping, debug points, stacks and more Feature Improvement
Projects
Status: New
Development

No branches or pull requests

3 participants