Skip to content

Debug adapter crashes when adding breakpoints for files that don't exist #195

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

Closed
daviwil opened this issue Mar 21, 2016 · 11 comments
Closed
Assignees
Labels
Issue-Bug A bug to squash.
Milestone

Comments

@daviwil
Copy link
Contributor

daviwil commented Mar 21, 2016

This can happen when VS Code keeps old breakpoints for files that have been renamed or deleted. See this bug report: PowerShell/vscode-powershell#121

The optimal behavior here is to send back information to VS Code saying that the breakpoint is unverified. Maybe there's a way to send an error saying that the breakpoint is completely invalid and should be removed?

Stack trace:

3/21/2016 7:51:58 AM [NORMAL] - Method "Main" at line 103 of C:\projects\powershelleditorservices\src\PowerShellEditorServices.Host\Program.cs

    PowerShell Editor Services Host v0.5.0.304 starting (pid 10796)...

3/21/2016 7:51:58 AM [NORMAL] - Method "Main" at line 112 of C:\projects\powershelleditorservices\src\PowerShellEditorServices.Host\Program.cs

    PowerShell Editor Services Host started!

3/21/2016 7:51:58 AM [VERBOSE] - Method "ReadMessage" at line 111 of C:\projects\powershelleditorservices\src\PowerShellEditorServices.Protocol\MessageProtocol\MessageReader.cs

    READ MESSAGE:

    {
      "type": "request",
      "seq": 1,
      "command": "initialize",
      "arguments": {
        "adapterID": "PowerShell",
        "pathFormat": "path",
        "linesStartAt1": true,
        "columnsStartAt1": true
      }
    }

3/21/2016 7:51:59 AM [VERBOSE] - Method "WriteMessage" at line 58 of C:\projects\powershelleditorservices\src\PowerShellEditorServices.Protocol\MessageProtocol\MessageWriter.cs

    WRITE MESSAGE:

    {
      "type": "event",
      "event": "initialized",
      "body": null
    }

3/21/2016 7:51:59 AM [VERBOSE] - Method "WriteMessage" at line 58 of C:\projects\powershelleditorservices\src\PowerShellEditorServices.Protocol\MessageProtocol\MessageWriter.cs

    WRITE MESSAGE:

    {
      "type": "response",
      "request_seq": "1",
      "command": "initialize",
      "success": true,
      "body": {
        "supportsConfigurationDoneRequest": true,
        "supportsFunctionBreakpoints": true,
        "supportsConditionalBreakpoints": true,
        "supportsEvaluateForHovers": false
      }
    }

3/21/2016 7:51:59 AM [VERBOSE] - Method "ReadMessage" at line 111 of C:\projects\powershelleditorservices\src\PowerShellEditorServices.Protocol\MessageProtocol\MessageReader.cs

    READ MESSAGE:

    {
      "type": "request",
      "seq": 2,
      "command": "setBreakpoints",
      "arguments": {
        "source": {
          "path": "c:\\Users\\Brian\\OneDrive\\Development\\GitHub\\ConnectWisePSModule\\src\\ConnectWisePSModule.psm1"
        },
        "lines": [
          295,
          356
        ],
        "breakpoints": [
          {
            "line": 295
          },
          {
            "line": 356
          }
        ]
      }
    }

3/21/2016 7:51:59 AM [VERBOSE] - Method "ResolveFilePath" at line 248 of C:\projects\powershelleditorservices\src\PowerShellEditorServices\Workspace\Workspace.cs

    Resolved path: c:\Users\Brian\OneDrive\Development\GitHub\ConnectWisePSModule\src\ConnectWisePSModule.psm1

3/21/2016 7:51:59 AM [ERROR] - Method "CurrentDomain_UnhandledException" at line 125 of C:\projects\powershelleditorservices\src\PowerShellEditorServices.Host\Program.cs

    FATAL UNHANDLED EXCEPTION:

    System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> System.IO.FileNotFoundException: Could not find file 'c:\Users\Brian\OneDrive\Development\GitHub\ConnectWisePSModule\src\ConnectWisePSModule.psm1'.
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
       at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean checkHost)
       at System.IO.StreamReader..ctor(String path, Encoding encoding)
       at Microsoft.PowerShell.EditorServices.Workspace.GetFile(String filePath)
       at Microsoft.PowerShell.EditorServices.Protocol.Server.DebugAdapter.<HandleSetBreakpointsRequest>d__15.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.MessageDispatcher.<DispatchMessage>d__32.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.MessageDispatcher.<ListenForMessages>d__31.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Utility.AsyncContext.Start(Func`1 asyncMainFunc)
       at System.Threading.Tasks.Task.Execute()
       --- End of inner exception stack trace ---
       --- End of inner exception stack trace ---
       at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
       at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
       at Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.ProtocolEndpoint.WaitForExit()
       at Microsoft.PowerShell.EditorServices.Host.Program.Main(String[] args)
    ---> (Inner Exception #0) System.AggregateException: One or more errors occurred. ---> System.IO.FileNotFoundException: Could not find file 'c:\Users\Brian\OneDrive\Development\GitHub\ConnectWisePSModule\src\ConnectWisePSModule.psm1'.
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
       at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean checkHost)
       at System.IO.StreamReader..ctor(String path, Encoding encoding)
       at Microsoft.PowerShell.EditorServices.Workspace.GetFile(String filePath)
       at Microsoft.PowerShell.EditorServices.Protocol.Server.DebugAdapter.<HandleSetBreakpointsRequest>d__15.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.MessageDispatcher.<DispatchMessage>d__32.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.MessageDispatcher.<ListenForMessages>d__31.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Utility.AsyncContext.Start(Func`1 asyncMainFunc)
       at System.Threading.Tasks.Task.Execute()
       --- End of inner exception stack trace ---
    ---> (Inner Exception #0) System.IO.FileNotFoundException: Could not find file 'c:\Users\Brian\OneDrive\Development\GitHub\ConnectWisePSModule\src\ConnectWisePSModule.psm1'.
    File name: 'c:\Users\Brian\OneDrive\Development\GitHub\ConnectWisePSModule\src\ConnectWisePSModule.psm1'
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
       at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean checkHost)
       at System.IO.StreamReader..ctor(String path, Encoding encoding)
       at Microsoft.PowerShell.EditorServices.Workspace.GetFile(String filePath)
       at Microsoft.PowerShell.EditorServices.Protocol.Server.DebugAdapter.<HandleSetBreakpointsRequest>d__15.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.MessageDispatcher.<DispatchMessage>d__32.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Protocol.MessageProtocol.MessageDispatcher.<ListenForMessages>d__31.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at Microsoft.PowerShell.EditorServices.Utility.AsyncContext.Start(Func`1 asyncMainFunc)
       at System.Threading.Tasks.Task.Execute()<---
    <---
@rkeithhill
Copy link
Contributor

This is an artifact of VSCode keeping track of the breakpoints by filename/line and not being savvy about the associated file being renamed, right?

If the file was renamed "within" and "by" VSCode then this seems like a VSCode bug. It should know what breakpoints are set in the file and update the filename appropriately when it is renamed. I wonder if an issue has been submitted to VSCode on this? That said, we can still fix the extension to not crash. :-)

@daviwil
Copy link
Contributor Author

daviwil commented Mar 21, 2016

I think the guy renamed the file outside of VS Code, or at least that's the impression I got. I'm guessing they aren't watching the filesystem for renames when a file gets renamed out of band.

@rkeithhill
Copy link
Contributor

I verified that VSCode moves the breakpoint accordingly if you rename the file within VSCode.

@rkeithhill rkeithhill self-assigned this Mar 25, 2016
@daviwil
Copy link
Contributor Author

daviwil commented Mar 25, 2016

That's good at least, means this probably hasn't been a major issue for users.

@rkeithhill
Copy link
Contributor

OK I have a fix for this but I'm a bit disappointed that when I return this message (note: verified = false):

    WRITE MESSAGE:

    {
      "type": "response",
      "request_seq": "2",
      "command": "setBreakpoints",
      "success": true,
      "body": {
        "breakpoints": [
          {
            "verified": false,
            "message": "Source does not exist, breakpoint not set.",
            "source": "c:\\Users\\Keith\\.vscode-insiders\\extensions\\ms-vscode.PowerShell-0.5.0\\examples\\DebugTest2.ps1",
            "line": 23,
            "column": null
          }
        ]
      }
    }

VSCode doesn't do anything with it AFAICT. I see no tooltip over the breakpoint. No popup. Nothing.

What's your policy on using the Debug Console? Should this only be for "script output" or can we output certain debug events (like VS does in its Output window)? Can/should we output something to the debug console indicating that the breakpoint was ignored? Or should we just rely on VSCode eventually getting around to doing something with the message we return? Also, any input on the wording for that message?

@daviwil
Copy link
Contributor Author

daviwil commented Apr 3, 2016

I don't have a problem with printing output, it'd be helpful in the short term if VS Code doesn't provide an integrated way to see the message. It looks like Set-PSBreakpoint actually prints an error if the file doesn't exist:

PS> Set-PSBreakpoint -Script c:\boo.ps1 -Line 20
Set-PSBreakpoint : Cannot find path 'C:\boo.ps1' because it does not exist.
At line:1 char:1
+ Set-PSBreakpoint -Script c:\boo.ps1 -Line 20
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\boo.ps1:String) [Set-PSBreakpoint],
   ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.SetPSBreakpoi
   ntCommand

I suppose we could just let it write its error to the host?

@daviwil
Copy link
Contributor Author

daviwil commented Apr 3, 2016

I'm also OK with having a less noisy output that is more appropriate for the console.

@rkeithhill
Copy link
Contributor

This is actually a good conversation to have as I'm catching the non-existing file at the protocol layer so I can respond with what I "believe" is the appropriate response to the client (even if they seem to ignore it for now). That said, I short-circuit the call down to the editor services layer. Perhaps I should catch the FileNotFoundException at the protocol layer but still call down to the editor services layer?? But then if VSCode ever does start displaying info to the user, the debug console output becomes a bit redundant. Hmmm.

@daviwil
Copy link
Contributor Author

daviwil commented Apr 3, 2016

Yeah, let's just show our own message for now. Once we start plugging in to other editors we may have to think a bit more about the right way to do this, but I think doing it at the protocol layer is a fine solution for now.

@rkeithhill
Copy link
Contributor

Hmm, one issue. At the protocol layer we try to look up a ScriptFile to pass down to the editor services method:

        public async Task<BreakpointDetails[]> SetLineBreakpoints(
            ScriptFile scriptFile, 
            BreakpointDetails[] breakpoints, 
            bool clearExisting = true)

But since the file doesn't exist, how do I pass it to this method other than to pass null for ScriptFile and get tricksy with how we handle null in this method?

I guess what we could do is add an overload that takes just a string path (which may not exist) and have the current method resolve ScriptFile to a string path and call the new overload. Thoughts?

@daviwil
Copy link
Contributor Author

daviwil commented Apr 5, 2016

Sorry for the delay, have been busy with stuff at the Summit. New changes look good to me!

rkeithhill added a commit that referenced this issue Apr 5, 2016
…onexisting-files

Fixes #195 - set breakpoint in non-existing file doesn't crash
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Bug A bug to squash.
Projects
None yet
Development

No branches or pull requests

2 participants