vscode-powershell: Debug Session not respecting Added or removed Breakpoints & Integrated Shell Crash

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

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 4
  • Comments: 18

Most upvoted comments

Ah, yes agreed!

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

Ok @GABeech I’ve done some research on this one and talked to @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 <kbd>F6</kbd>) button will stop pipeline execution. It hooks into the same API that the ISE uses with <kbd>Ctrl</kbd>+<kbd>Break</kbd> and PowerShell itself (the ConHost) uses with <kbd>Ctrl</kbd>+<kbd>B</kbd>.

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

  • <kbd>F6</kbd> (Pause)
  • Set the breakpoint
  • <kbd>F5</kbd> (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.

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.

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

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