ionide-vscode-fsharp icon indicating copy to clipboard operation
ionide-vscode-fsharp copied to clipboard

Can Ionide debug fsx scripts?

Open ktodyruik opened this issue 5 years ago • 16 comments

Hi,

This is just a question. Can Ionide debug fsx scripts?

ktodyruik avatar Feb 20 '20 17:02 ktodyruik

Hey @ktodyruik :wave:,

Thank you for opening an issue. We will get back to you as soon as we can. Also, check out our OpenCollective and consider backing us.

https://opencollective.com/ionide

PS.: We offer backer support for all backers. Don't forget to add backer label when you start backing us :smile:

No, we don't support debugging fsx scripts at the moment

Krzysztof-Cieslak avatar Mar 18 '20 16:03 Krzysztof-Cieslak

Do you think we can request support for script debugging? Would it be helpful in the script context and data/python/like context? cc @Krzysztof-Cieslak

jkone27 avatar Jul 12 '23 12:07 jkone27

Wouldn't be opposed to taking a PR for this.

As a workaround for now you can do something like:

open System.Diagnostics



let waitForDebuggerAttached (programName) =
    if not (System.Diagnostics.Debugger.IsAttached) then
        printfn
            "Please attach a debugger for %s, PID: %d"
            programName
            (System.Diagnostics.Process.GetCurrentProcess().Id)
    while not (System.Diagnostics.Debugger.IsAttached) do
        System.Threading.Thread.Sleep(100)


let breakPoint () =
    Debugger.Break ()


let main () =

    printfn "doing something"
    waitForDebuggerAttached "playground.fsx"
    let foo = "42"
    printfn "%A" fsi.CommandLineArgs
    breakPoint ()
    failwith "fail"
    ()

main ()

and having .vscode/launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach",
            "requireExactSource" : false,
            "justMyCode": false
        }

    ]
}

TheAngryByrd avatar Jul 12 '23 13:07 TheAngryByrd

Alternative - debugging a script in that way introduces new sources, could a launch request be used instead that launches the dotnet binary with [fsi, path/to/script.fsx] args and a debugOnStart flag set?

baronfel avatar Jul 12 '23 13:07 baronfel

Alternative - debugging a script in that way introduces new sources, could a launch request be used instead that launches the dotnet binary with [fsi, path/to/script.fsx] args and a debugOnStart flag set?

I think I remember from awhile ago, the issue is the fsx code gets run in another process so I don't think you end up debugging the right thing.

TheAngryByrd avatar Jul 12 '23 13:07 TheAngryByrd

Oh that's right - dotnet fsi shells out to the fsi dll. We'd need to run fsi.dll in-proc. You can still simulate that though. Here's a configuration that mostly-worked for me:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch FSI",
            "request": "launch",
            "type": "coreclr",
            "program": "C:\\Program Files\\dotnet\\sdk\\8.0.100-preview.5.23303.2\\FSharp\\fsi.dll",
            "args": ["${workspaceFolder}\\tryMakeTfmHashes.fsx", "--debug+", "--debug:portable", "--optimize-"],
            "justMyCode": false
        }
    ]
}

We should consider auto-creating this configuration when an FSI file is launched for debugging.

There are caveats here though - locals/watches seem to not work at all in this case. I've tried adding debugging flags to make the experience better but I'm not sure I've got the right combination. Locals inside loops/bindings/etc work, but once you're outside of that scope there's just nothing.

baronfel avatar Jul 12 '23 14:07 baronfel

@baronfel tested the last approach it works, but indeed no watch or scope variables during debug!

Internal error in the C# compiler

here was my github codespace config for launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch FSI",
            "request": "launch",
            "type": "coreclr",
            "program": "/home/codespace/.dotnet/sdk/7.0.302/FSharp/fsi.dll",
            "args": ["${workspaceFolder}/program.fsx", "--debug+", "--debug:portable", "--optimize-"],
            "justMyCode": false
        }
    ]
}

is there a way to autodetect SDK version also, maybe with a ENV variable like ${workspaceFolder}, something like ${dotnetSdkVersion}, maybe exists...

image

jkone27 avatar Jul 16 '23 11:07 jkone27

I started a conversation with @vlza on the FSSF slack that had some pointers - private thread link is https://fsharp.slack.com/archives/C04AUG3RBGE/p1689174015344819?thread_ts=1689174015.344819&cid=C04AUG3RBGE for posterity.

A couple things to try:

Every submission for fsi generates another Assembly, with top levels being internal fields, and we emit IVT for next assemblies. Or at least we used to manually go check and have a module with public bindings in it, are they visible (as opposed to internal) Don't we emit things as internal in fsi assemblies? Does netcoredbg care about that?

If we can dig into what's going on here and get locals to show up, then Ionide/FSAC could generate the appropriate launch config for the user and we wouldn't need the SDK placeholder variables like @jkone27 was mentioning.

baronfel avatar Jul 16 '23 11:07 baronfel

ah i see dotnet fsi debugging was implemented here - https://github.com/dotnet/fsharp/pull/12722 also locals error seems related or similar to this one - https://github.com/dotnet/vscode-csharp/issues/3926

added C#/dotnet debugger log

"logging": {
            "engineLogging": true
        }

in vscode launch.json and I see this msg

<- (E) {"seq":167,"type":"event","event":"output","body":{"category":"console","output":"Loaded '/usr/local/dotnet/7.0.302/shared/Microsoft.AspNetCore.App/7.0.5/Microsoft.Extensions.Configuration.EnvironmentVariables.dll'. Cannot find or open the PDB file.\n"}}
Loaded '/usr/local/dotnet/7.0.302/shared/Microsoft.AspNetCore.App/7.0.5/Microsoft.Extensions.Configuration.EnvironmentVariables.dll'. Cannot find or open the PDB file.
<- (E) {"seq":168,"type":"event","event":"module","body":{"reason":"new","module":{"id":1063,"name":"Microsoft.Extensions.Configuration.EnvironmentVariables.dll","path":"/usr/local/dotnet/7.0.302/shared/Microsoft.AspNetCore.App/7.0.5/Microsoft.Extensions.Configuration.EnvironmentVariables.dll","isOptimized":true,"isUserCode":false,"version":"7.00.22.51805","symbolStatus":"Cannot find or open the PDB file."}}}
<- (R) {"seq":313,"type":"response","request_seq":19,"success":true,"command":"scopes","body":{"scopes":[{"name":"Locals","variablesReference":1000,"expensive":false}]}}
-> (C) {"command":"variables","arguments":{"variablesReference":1000},"type":"request","seq":20}
<- (R) {"seq":314,"type":"response","request_seq":20,"success":false,"command":"variables","message":"Error processing 'variables' request. An exception was thrown from a debugger component."}

jkone27 avatar Jul 16 '23 12:07 jkone27

@jkone27 you should be able to set '--debug:portable' to generate portable symbols for the FSI session. That may also need '--multiemit' (which IIRC is the default) to emit each interaction as a separate assembly...

I tried these options a bit locally and still didn't get locals (but I may not have updated my initial comment here)

baronfel avatar Jul 16 '23 12:07 baronfel

added Microsoft.Extensions.Configuration in open statement and nuget ref (in case that can add .pdb debug files), I see this exception at debug "startup" , not sure if related

<- (R) {"seq":69,"type":"response","request_seq":14,"success":true,"command":"variables","body":{"variables":[{"name":"$exception [InvalidOperationException]","value":
"{System.InvalidOperationException: Cannot see if a key has been pressed when either application does not have a console or when console input has been redirected from a file. Try Console.In.Peek.\n   at System.Console.get_KeyAvailable()}","type":"System.InvalidOperationException","presentationHint":{"kind":"data","attributes":["canHaveObjectId","readOnly"]},
"evaluateName":"$exception","variablesReference":1001,"memoryReference":"0x00007EE2A144E2B0"},{"name":"console","value":"{FSharp.Compiler.Interactive.ReadLineConsole}",
"type":"FSharp.Compiler.Interactive.ReadLineConsole","presentationHint":{"kind":"data","attributes":["canHaveObjectId"]},"evaluateName":"console","variablesReference":1002,"memoryReference":"0x00007EE2A140E040"},{"name":"probeToSeeIfConsoleWorks [bool]","value":
"Cannot obtain value of the local variable or argument because it is not available at this instruction pointer, possibly because it has been optimized away.","type":"bool","presentationHint":{"attributes":["isBoolean","readOnly","failedEvaluation"]},"variablesReference":0}]}}
image

Sorry I see is in try catch so this seems for sure unrelated (?) probably

jkone27 avatar Jul 16 '23 12:07 jkone27

with --multiemit got this one instead :) seems related to Saturn lib

Exception has occurred: CLR/System.IO.FileNotFoundException
Exception thrown: 'System.IO.FileNotFoundException' in System.Private.CoreLib.dll: 'Could not load file or assembly '/home/codespace/.nuget/packages/saturn/0.16.1/lib/net6.0/Microsoft.Extensions.Logging.Abstractions.dll'. The system cannot find the file specified.'
   at System.Runtime.Loader.AssemblyLoadContext.<LoadFromPath>g____PInvoke|5_0(IntPtr ptrNativeAssemblyBinder, UInt16* ilPath, UInt16* niPath, ObjectHandleOnStack retAssembly)

jkone27 avatar Jul 16 '23 12:07 jkone27

in my latest test run i cannot debug anymore, cannot open pdb files.. with the same settings, no breakpoints hit... regression.

Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.11/System.Private.CoreLib.dll'. Cannot find or open the PDB file.
Loaded '/usr/local/share/dotnet/sdk/7.0.401/FSharp/fsi.dll'. 
Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.11/System.Runtime.dll'. Cannot find or open the PDB file.
Loaded '/usr/local/share/dotnet/sdk/7.0.401/FSharp/FSharp.Core.dll'. 
Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.11/netstandard.dll'. Cannot find or open the PDB file.
Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.11/System.Console.dll'. Cannot find or open the PDB file.
Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.11/System.Threading.dll'. Cannot find or open the PDB file.
Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/7.0.11/System.Runtime.InteropServices.dll'. Cannot find or open the PDB file.

jkone27 avatar Oct 19 '23 17:10 jkone27

Unfortunately I don't think this is related to anything we control. This is probably an issue in fsi or the debugger for vscode itself.

TheAngryByrd avatar Oct 24 '23 19:10 TheAngryByrd

Possibly relevant: https://github.com/dotnet/fsharp/issues/15820

smoothdeveloper avatar Oct 24 '23 21:10 smoothdeveloper