Debug Session not respecting Added or removed Breakpoints & Integrated Shell Crash · Issue #1494 · PowerShell/vscode-powershell · GitHub
Skip to content

Debug Session not respecting Added or removed Breakpoints & Integrated Shell Crash #1494

Open

Description

@GABeech

Issue Description

When I run a debug session two things happen:

  1. Any addition or removal of breakpoints is not respected
  2. The Integrated shell Crashes after not exiting correctly

You can replicate this by running a small script like:

while ($true)
{
  Write-Output "I'm In a loop"
  Start-Sleep 10
  Write-Output "I just woke up"
}

Removing Breakpoint

  • Set a breakpoint on the first Write-Output
  • Debug The script
  • Remove Breakpoint on First Write-Output
  • Continue running

What will happen is the debugger will break again on the first Write-Output and you won't be able to continue. If you stop execution and type exit in the debug terminal the integrated terminal will crash

Adding Breakpoint

  • Debug the script
  • Set a breakpoint anywhere in the while loop
  • It will never be hit.

Attached Logs

EditorServices.log
vscode-powershell.log

) about
capturing and sending logs.

Environment Information

Visual Studio Code

Name Version
Operating System Windows_NT x64 10.0.16299
VSCode 1.26.1
PowerShell Extension Version 1.8.3

PowerShell Information

Name Value
PSVersion 5.1.16299.492
PSEdition Desktop
PSCompatibleVersions 1.0 2.0 3.0 4.0 5.0 5.1.16299.492
BuildVersion 10.0.16299.492
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

Visual Studio Code Extensions

Visual Studio Code Extensions(Click to Expand)
Extension Author Version
aspnet-helper schneiderpat 0.6.4
ecdc mitchdenny 0.12.0
EditorConfig EditorConfig 0.12.4
github-issues-prs ms-vscode 0.9.0
gitlens eamodio 8.5.6
jenkins-declarative-support jmMeessen 0.1.0
markdown-all-in-one yzhang 1.6.0
PowerShell ms-vscode 1.8.3
python ms-python 2018.7.1
rainbow-csv mechatroner 0.4.2
vscode-github KnisterPeter 0.30.0
vscode-icons robertohuertasm 7.25.0
vscode-markdownlint DavidAnson 0.20.0
vscode-mermaid-preview vstirbu 0.10.1
xml DotJoshJohnson 2.3.2

Activity

  1. changed the title [-]Debug Session no respecting Added or removed Breakpoints & Integrated Shell Crash[/-] [+]Debug Session not respecting Added or removed Breakpoints & Integrated Shell Crash[/+] on Aug 22, 2018
  2. rjmholt commented on Aug 23, 2018

    @rjmholt
    Contributor

    Thanks for opening an issue George Beech (@GABeech). I can reproduce this on my machine. I've been looking into it but haven't found the cause yet. Will continue investigating.

  3. rjmholt commented on Aug 23, 2018

    @rjmholt
    Contributor
  4. SeeminglyScience commented on Aug 23, 2018

    @SeeminglyScience
    Collaborator

    Rob Holt (@rjmholt) If you have the PSRL build still, see if you can reproduce it there. I made a lot of changes around the runspace handle queues.

  5. rjmholt commented on Oct 8, 2018

    @rjmholt
    Contributor

    So I did some more investigating on this today.

    The breakpoint is set correctly and unset correctly, but trying to set it again does nothing at all. This is almost certainly because PSES is being blocked by the current execution.

    I was curious as to where PSES thought it was, so I paused the PSES .NET debugger and on my Windows machine in 1.9.1, it reports itself as being here:
    https://github.com/PowerShell/PowerShellEditorServices/blob/f1ab46289904b77fe5f5bd97cc89e2f5286444db/src/PowerShellEditorServices/Console/WindowsConsoleOperations.cs#L22

    In v2, I think it reports itself as being here:
    https://github.com/PowerShell/PowerShellEditorServices/blob/67af23203c0d7aac52a6c5655d7d7f1202e80dd0/src/PowerShellEditorServices/Session/PowerShellContext.cs#L651

    I think it basically comes down to the debug adapter not being able to interrupt the script to add a new breakpoint -- which is obviously a problem.

    In 1.9.1 I get no crash (or at least I didn't this time). But with v2 I got a pipe broken error, which I think we've seen can also occur in 1.9.1.

  6. rjmholt commented on Oct 10, 2018

    @rjmholt
    Contributor

    After looking into this and thinking about it a bit, this looks like a deeper issue -- I'll see what we can do to fix it, but I think we will need to do some cleverness with interrupting the execution of the PowerShell pipeline.

  7. SeeminglyScience commented on Oct 10, 2018

    @SeeminglyScience
    Collaborator

    We could implement this in 2.0. Taking over script execution between sequence points can be done with events, but that requires all the nested context work done for PSReadLine.

  8. rjmholt commented on Oct 10, 2018

    @rjmholt
    Contributor

    If we can engineer that, it would be useful in a whole bunch of cases for cancellation of the PowerShell executions powering most requests -- so we could finally implement $/cancelRequest properly.

  9. SeeminglyScience commented on Oct 10, 2018

    @SeeminglyScience
    Collaborator

    We can already trigger a pipeline stop from any thread, the engine supports that. Just gotta tie a request to a powershell instance

  10. rjmholt commented on Oct 16, 2018

    @rjmholt
    Contributor

    Ok George Beech (@GABeech) I've done some research on this one and talked to Paul Higinbotham (@PaulHigin) as well, who is our debugger expert.

    Because the PowerShell debugger is just PowerShell, setting a breakpoint while the pipeline is running is a bit trickier than for other languages. As far as I know, it's something that neither PowerShell nor the ISE has directly supported.

    But, experimenting with your scenario, using the pause (⏸ or F6) button will stop pipeline execution. It hooks into the same API that the ISE uses with Ctrl+Break and PowerShell itself (the ConHost) uses with Ctrl+B.

    So the current way to set a breakpoint while a script is running like in the scenario above it:

    • F6 (Pause)
    • Set the breakpoint
    • F5 (Continue)

    Bear in mind that if you have a single long running command or .NET call, this can't pause that. There's no mechanism for that anywhere, because the PowerShell debugger is PowerShell -- it can't stop in the middle of a native or .NET call.

    I'm looking into how we might make this automatic -- so that when you set a breakpoint, it will stop the pipeline, insert the breakpoint and then continue on its way. But it's complicated by needing to sync up VSCode's client state.

  11. SeeminglyScience commented on Oct 16, 2018

    @SeeminglyScience
    Collaborator

    Rob Holt (@rjmholt) We could use events. I think this should be safe from issues like the completion deadlock.

    Here's a little sample:

    $timer = [System.Timers.Timer]::new(60000)
    Register-ObjectEvent -InputObject $timer -EventName Elapsed -Action {
        $Event | Unregister-Event
        Set-PSBreakpoint -Variable someSpecificVar -Mode Write
    }
    
    $timer.Enabled = $true
    
    # After a minute, the debugger will break on the someSpecificVar assignment.
    while ($true) {
        $someSpecificVar = $true
        Start-Sleep 5
    }

    We would probably want register it on an event on PowerShellContext instead of Timer, that's just for the PoC. The idea is that PowerShell events like those register via Register-ObjectEvent will be processed between sequence points if a script is running. This still won't help in situations where a single sequence point is taking a long time, but we can't really do anything about that.

  12. rkeithhill commented on Oct 16, 2018

    @rkeithhill
    Contributor

    Does OnIdle execute between pipeline invocations? If so, we could queue up breakpoint requests and execute them then.

  13. SeeminglyScience commented on Oct 16, 2018

    @SeeminglyScience
    Collaborator

    Keith Hill (@rkeithhill) Not sure what the usual timeout is for OnIdle, with PSReadLine it's 200ms (or immediately when we ask it to check for events). I know for sure it won't execute between sequence points of a long running script though.

    Same idea though, we would queue up breakpoints by raising an event on an object we control and the subscriber would get to it at the next sequence point.

  14. rjmholt commented on Oct 16, 2018

    @rjmholt
    Contributor

    Keith Hill (@rkeithhill) I don't think OnIdle events are raised between pipeline invocations, but could be wrong.

    The reason I mention our debugService.Break() method, is because I think it actually uses the right API:

    It's what the ISE uses for interrupting a currently running script to break into it.

    Is there a reason using that is a bad idea for us?

  15. SeeminglyScience commented on Oct 16, 2018

    @SeeminglyScience
    Collaborator

    Rob Holt (@rjmholt) I could be wrong but I believe that just tells the debugger that it should pause at the next sequence point. I don't think it synchronously stops the debugger.

  16. rjmholt commented on Oct 16, 2018

    @rjmholt
    Contributor

    Right, it just says "please pause the debugger at the next opportunity". Is there a way we think we can/should be doing better than that?

  17. SeeminglyScience commented on Oct 16, 2018

    @SeeminglyScience
    Collaborator

    We're not specifically trying to stop the debugger right? If we're just trying to set a breakpoint then I think the event route is cleaner. We could stop the debugger, then in the PowerShellContext.OnDebuggerStop method we could set queued breakpoints and possibly exit early, that seems like a lot of extra state to manage though.

  18. rjmholt commented on Oct 16, 2018

    @rjmholt
    Contributor

    Ah, yes agreed!

    It seems like an API we ought to have on PowerShellContext -- like QueueSequencePointCommand or something

  19. PaulHigin commented on Oct 17, 2018

    @PaulHigin

    Sorry for the late contribution. If I understand the issue correctly, engine events are not needed to manage script breakpoints. But the only way to update script breakpoints on running script is to, as discussed above:
    a. Break into the debugger (set to step mode)
    b. Add/remove/enable/disable breakpoints
    c. Resume script execution

    Note that the first step (a.) can be problematic if the script is not running but is stalled during a dotNet API call or while running a native command. The debugger stop event will not occur until the next sequence point is executed.

    Breaking into the debugger can be done via the ScriptDebugger.SetDebuggerStepMode() method, and engine events are not needed. The method can be called from any thread. Then as Patrick Meinecke (@SeeminglyScience) mentions, breakpoints can be managed during the DebuggerStop event callback via the ScriptDebugger.ProcessCommand() method.

  20. removed their assignment
    on Oct 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions