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

Can Ionide debug fsx scripts? #1309

Open
ktodyruik opened this issue Feb 20, 2020 · 16 comments
Open

Can Ionide debug fsx scripts? #1309

ktodyruik opened this issue Feb 20, 2020 · 16 comments

Comments

@ktodyruik
Copy link

Hi,

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

@open-collective-bot
Copy link

Hey @ktodyruik 👋,

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 😄

@Krzysztof-Cieslak
Copy link
Member

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

@jkone27
Copy link

jkone27 commented Jul 12, 2023

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

@TheAngryByrd
Copy link
Member

TheAngryByrd commented Jul 12, 2023

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
        }

    ]
}

@baronfel
Copy link
Contributor

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?

@TheAngryByrd
Copy link
Member

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.

@baronfel
Copy link
Contributor

baronfel commented Jul 12, 2023

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.

@jkone27
Copy link

jkone27 commented Jul 16, 2023

@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

@baronfel
Copy link
Contributor

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.

@jkone27
Copy link

jkone27 commented Jul 16, 2023

ah i see dotnet fsi debugging was implemented here - dotnet/fsharp#12722
also locals error seems related or similar to this one - dotnet/vscode-csharp#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."}

@baronfel
Copy link
Contributor

@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)

@jkone27
Copy link

jkone27 commented Jul 16, 2023

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
Copy link

jkone27 commented Jul 16, 2023

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
Copy link

jkone27 commented Oct 19, 2023

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.

@TheAngryByrd
Copy link
Member

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.

@smoothdeveloper
Copy link

Possibly relevant: dotnet/fsharp#15820

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants