-
Notifications
You must be signed in to change notification settings - Fork 235
Fix debugger step through on Unix platforms #592
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
Fix debugger step through on Unix platforms #592
Conversation
This change resolves an issue where the debugger would appear hung until a key was pressed on Unix platforms. This issue was caused by a quirk with the Unix implementation for System.Console. The way cursor position is retreived is by writing the cursor position escape sequence query and reading it from stdin. To ensure those escape sequences don't trigger `Console.ReadKey`, the internal stdin buffer is locked while `ReadKey` is running. This means that while `ReadKey` is running, any attempts to query cursor position will block the thread until the pending `ReadKey` finishes. The pipeline appears to hang on a debugger stop because there is a pending `ReadKey` call in another thread and various methods in both the internal PowerShell engine and in our host implementation obtain the cursor position between command executions to determine prompt location. The best solution to this problem (credit goes to @rkeithhill) is to create an alternative `ReadKey` implementation that waits for `KeyAvailable` before blocking. However, if `ReadKey` is not currently running then any input is echoed to the console. Aside from being generally annoying, this presents a huge problem while trying to do something like `Read-Host -AsSecureString`. To get around this, I stripped out the native code from corefx that disables console input echo, created a separate package that this project can consume, and implemented a `WaitForKeyAvailable` method that utilizes it. This fix should be viewed as a temporary solution until either `ReadKey` acts like this by default or a `ReadKeyAsync` method is implemented into corefx.
@tylerl0706 Could you restart the AppVeyor build when you get a minute? I believe that's the test issue that happens intermittently. |
Awesome! I'll test this on Mac later today. Let me restart that build for you... |
Should I just go through the steps in each of those issues? Or do you have a specific set of steps you want me try? |
Good question, I would say the important things to try would be
Edit: Also for anyone patiently awaiting this fix, if you want to try it early you can grab the AppVeyor build here. |
NYE got in the way! I'll take care of this... next year 😄 (tomorrow or Tuesday). Happy New Year! |
Can anyone validate if this fix works with function breakpoints ? i'm crashing everytime i set a function breakpoint (for example, when using the sample scripts provided with the powershell plug in like in DebugTest.ps1) |
1: Didn't have to hit 2: I spammed the Integrated Console pretty hard and didn't see any hiccups! 3: 😄
The code is good for macOS 🎉 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but I think @rkeithhill and @daviwil should take a look at this.
@@ -129,6 +129,10 @@ task TestPowerShellApi -If { !$script:IsUnix } { | |||
task Build { | |||
exec { & $script:dotnetExe build -c $Configuration .\src\PowerShellEditorServices.Host\PowerShellEditorServices.Host.csproj $script:TargetFrameworksParam } | |||
exec { & $script:dotnetExe build -c $Configuration .\src\PowerShellEditorServices.VSCode\PowerShellEditorServices.VSCode.csproj $script:TargetFrameworksParam } | |||
exec { & $script:dotnetExe publish -c $Configuration .\src\PowerShellEditorServices\PowerShellEditorServices.csproj -f netstandard1.6 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious - why are you are calling dotnet publish
? Does a normal build not have what you're looking for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, dependencies aren't copied on build
when you target standard or core. publish
is supposed to the the final product with everything needed to run including packages, runtimes and framework assemblies. Most of that is already provided by being hosted in PowerShell though, so I just pick out what's needed.
(newb question) i'm running version 1.5.1 of the VSCode Powershell plugin, will there be another release of the plugin added ? or if i want to test this i will need to rebuild the plugin myself ? |
@realonedet it would be in the next release. But if you want to try it out early, you can grab the built version from appveyor (here's a direct link). Extra testing before release is very helpful and always welcome :) |
exec { & $script:dotnetExe publish -c $Configuration .\src\PowerShellEditorServices\PowerShellEditorServices.csproj -f netstandard1.6 } | ||
Copy-Item $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\netstandard1.6\publish\UnixConsoleEcho.dll -Destination $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6 | ||
Copy-Item $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\netstandard1.6\publish\runtimes\osx-64\native\libdisablekeyecho.dylib -Destination $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6 | ||
Copy-Item $PSScriptRoot\src\PowerShellEditorServices\bin\$Configuration\netstandard1.6\publish\runtimes\linux-64\native\libdisablekeyecho.so -Destination $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not my wheelhouse but are we comfortable that this .so (and the above .dylib) will work on all OS distributions supported by VSCode?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rkeithhill Good question, I initially only tested on Ubuntu. I just pulled the microsoft/powershell
docker images for centos7
, opensuse42.1
, and opensuse13.2
to make sure they at least can load the lib and turn off echo. But that's not a full test, and I don't know enough about docker and Linux to know if what I did is even an accurate test. I'm pretty comfortable because of how small the code is, but I definitely can't say with absolute certainly that it will work everywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could maybe be a little bit more certain on docker by installing vscode in the image along with some vnc server. Then you should be able to rdp/vnc into the container and mess around with VSCode to verify the fix.
It's possibly a bit lengthly, but if you want to be more certain, it will certainly help.
I'm not actually 100% certain if this is possible though - haven't tried it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tylerl0706 Yeah for sure, though it sounds like about the same time and effort as spinning up a vm for each distro. Either way that's a bit more involved than I have the bandwidth for, but if someone wants to take that up I'm all for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll make some Dockerfiles one of these days that can grab the distros, install PowerShell, VNC, VSCode, and the extension so we have them for next time.
So the extension supports feature flags via the setting:
Those get passed down to PSES. Would it be reasonable to firewall the new code behind a feature flag and tell folks how to enable the feature on Linux/macOS? Not sure how hard that would be with this change. We used to firewall features like this on a cross-platform project I worked on back in the 90's - yeah dating myself a bit here. OTOH the current debugging situation on Linux/macOS is so horribly broken it is hard to imagine this could make it worse. :-) |
IMO, I'm fine with just shipping it 🚢 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Should we merge this, or wait for @daviwil? Your call @SeeminglyScience! |
Just one question to the room, is there an opportunity to add tests for this PR at all? |
@tylerl0706 Let's go ahead and merge. Though, you're right, tests would be good. Not sure exactly when I'll get around to that. We can either keep this open until then, or merge it now and open an issue to track the need for tests. I'd prefer the latter, but I'll leave that up to you. |
Oh also, I'm open to putting this behind a feature flag. If only because it'd be nice to have that capability nailed down before PSReadLine, which will definitely need to be behind a feature flag. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SeeminglyScience is a superhero. Thanks a ton for working so hard to get this fixed!
@@ -466,41 +487,6 @@ public Task<string> ReadSimpleLine(CancellationToken cancellationToken) | |||
return null; | |||
} | |||
|
|||
private async Task<ConsoleKeyInfo> ReadKeyAsync(CancellationToken cancellationToken) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really happy to get rid of this horrible piece of code :)
@@ -185,9 +189,12 @@ task LayoutModule -After Build { | |||
New-Item -Force $PSScriptRoot\module\PowerShellEditorServices\bin\Core -Type Directory | Out-Null | |||
|
|||
Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6\* -Filter Microsoft.PowerShell.EditorServices*.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ | |||
Copy-Item -Force -Path $PSScriptRoot\src\PowerShellEditorServices.Host\bin\$Configuration\netstandard1.6\UnixConsoleEcho.dll -Destination $PSScriptRoot\module\PowerShellEditorServices\bin\Core\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tylerl0706 before you can ship these binaries with PSES and the PowerShell extension, you'll need to request OSS approval for Patrick's library. You may also need to include his copyright in a Third Party Notices file like the one in the PS extension. I highly doubt they will reject the request to use this code but better to follow the necessary process anyway :)
@SeeminglyScience I got approval to use your library 🎉 Let's merge this in and I'll add the Third Party Notices. |
@SeeminglyScience I tried the code from the appveyor link (replacing the directories in the zip in the powershell modules folders), the behavior did not change, i'm still crashing as soon as i debug code with breakpoints set (i'm just trying to debug the sample code that comes with the Powershell AddIn). Any ideas ? #StillFrustrated |
@realonedet Hmm that may be a different issue then. Could you open an issue and include verbose logs from right after a crash? (Capturing verbose logs) |
Fix PowerShell#591: Sort "editor commands" by their name for menu display
This change resolves an issue where the debugger would appear hung until a key was pressed on Unix platforms.
This issue was caused by a quirk with the Unix implementation for
System.Console
. The way cursor position is retrieved is by writing the cursor position escape sequence query and reading it from stdin. To ensure those escape sequences don't triggerConsole.ReadKey
, the internal stdin buffer is locked whileReadKey
is running. This means that whileReadKey
is running, any attempts to query cursor position will block the thread until the pendingReadKey
finishes.The pipeline appears to hang on a debugger stop because there is a pending
ReadKey
call in another thread and various methods in both the internal PowerShell engine and in our host implementation obtain the cursor position between command executions to determine prompt location.The best solution to this problem (credit goes to @rkeithhill) is to create an alternative
ReadKey
implementation that waits forKeyAvailable
before blocking. However, ifReadKey
is not currently running then any input is echoed to the console. Aside from being generally annoying, this presents a huge problem while trying to do something likeRead-Host -AsSecureString
.To get around this, I stripped out the native code from corefx that disables console input echo, created a separate package that this project can consume, and implemented a
WaitForKeyAvailable
method that utilizes it.This fix should be viewed as a temporary solution until either
ReadKey
acts like this by default or aReadKeyAsync
method is implemented into corefx.@tylerl0706 I've tested on Windows and Linux, but it still needs to be tested on Mac. Thanks again for your help with building! :)
Resolves PowerShell/vscode-powershell#987
Resolves PowerShell/vscode-powershell#1107
Resolves #554