Skip to content

OnIdle Doesn't Seem to Fire Until PowerShell is Not Idle #1092

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
nickcox opened this issue Oct 9, 2019 · 15 comments
Closed

OnIdle Doesn't Seem to Fire Until PowerShell is Not Idle #1092

nickcox opened this issue Oct 9, 2019 · 15 comments

Comments

@nickcox
Copy link

nickcox commented Oct 9, 2019

Environment data

PS version: 7.0.0-preview.4
PSReadline version: 2.0.0-beta5
os: Darwin Nick-Coxs-Macbook-Pro.local 18.7.0 Darwin Kernel Version 18.7.0: Tue Aug 20 16:57:14 PDT 2019; root:xnu-4903.271.2~2/RELEASE_X86_64 x86_64
PS file version: 7.0.0.0
HostName: ConsoleHost
BufferWidth: 238
BufferHeight: 59

Steps to reproduce or exception report

Without PSReadLine

❯ pwsh -nologo -noprofile
PS /Users/nick.cox> Remove-Module PSReadline
PS /Users/nick.cox> $null = Register-EngineEvent -SourceIdentifier PowerShell.OnIdle -Action {Write-Host  '*idle*'} -MaxTriggerCount 3
PS /Users/nick.cox> *idle*
*idle*
*idle*

With PSReadLine

❯ pwsh -nologo -noprofile
PS /Users/nick.cox> Get-Module PSReadline
ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     2.0.0      PSReadLine                          {Get-PSReadLineKeyHandler, Get-PSReadLineOption, Remove-PSReadLineKeyHandler, Set-PSReadLineKeyHandler…}

PS /Users/nick.cox> $null = Register-EngineEvent -SourceIdentifier PowerShell.OnIdle -Action {Write-Host  '*idle*'} -MaxTriggerCount 3
PS /Users/nick.cox> *idle*
# ... (nothing happens until I press a key)
a*idle*
aa*idle*
@msftrncs
Copy link
Collaborator

msftrncs commented Oct 9, 2019

What are you expecting differently, and how does it relate to PSReadline? To me, it seems to be working as one would expect. I almost immediately get the 'idle', once, as was requested.

@nickcox
Copy link
Author

nickcox commented Oct 9, 2019

Sorry, I didn't explain that very well.

What are you expecting differently

I would expect to almost immediately see *idle*, once, as was requested

how does it relate to PSReadline?

Here are the two scenarios:

Without PSReadLine

❯ pwsh -nologo -noprofile
PS /Users/nick.cox> Remove-Module PSReadline
PS /Users/nick.cox> $null = Register-EngineEvent -SourceIdentifier PowerShell.OnIdle -Action {Write-Host  '*idle*'} -MaxTriggerCount 1
PS /Users/nick.cox> *idle*

The event is triggered almost immediately, as one would expect.

With PSReadLine

❯ pwsh -nologo -noprofile
PS /Users/nick.cox> Get-Module PSReadline
ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     2.0.0      PSReadLine                          {Get-PSReadLineKeyHandler, Get-PSReadLineOption, Remove-PSReadLineKeyHandler, Set-PSReadLineKeyHandler…}

PS /Users/nick.cox> $null = Register-EngineEvent -SourceIdentifier PowerShell.OnIdle -Action {Write-Host  '*idle*'} -MaxTriggerCount 1
PS /Users/nick.cox> # nothing happens until I press a key

Do you see what I mean?

What operating system are you on? I'm pretty sure I tested this previously on Windows and it worked well (on beta4 and beta5).

@nickcox
Copy link
Author

nickcox commented Oct 9, 2019

@msftrncs I've just tested this on my Windows machine and can confirm that it seems fine there.

Does the above make sense? Is there anything else I can do to help you get to the bottom of this?

@SeeminglyScience
Copy link
Contributor

@msftrncs This is a bug/quirk with how System.Console works on non-Windows platforms (see #626 and dotnet/corefx#25036 for more details). There aren't any particularly good ways of solving this currently.

@lzybkr
Copy link
Contributor

lzybkr commented Oct 9, 2019

We could revisit calling the C# api directly from the console host instead of calling the PowerShell function.

I ran into difficulties when I tried that originally, but I don't recall what issues there were in invoking custom keybindings.

@SeeminglyScience
Copy link
Contributor

Right now the issue is that Console.ReadKey is blocking on one thread, and then on the pipeline thread cursor position is checked before triggering events. The call to ReadKey will hold corefx's internal lock on stdin, then the cursor position query will attempt to acquire that same lock (in core 3.0 it's not every time, but frequently enough that it's not a fix). That causes the pipeline thread to block until ReadKey completes. Afaict that wouldn't change if PSConsoleHostReadLine was skipped.

I think you discussed removing that cursor position check in the ReadKey timeout loop at one point. If nothing else queries cursor position that will work. I vaguely remember something in the general pipeline spin up/wind down code path that queries cursor position but I might be thinking of ConsoleHost. Though if an event handler needed to check cursor position it would still lock.

@lzybkr
Copy link
Contributor

lzybkr commented Oct 9, 2019

I was suggesting that if the console host calls the C# api directly, we could avoid having the pipeline thread be blocked completely - e.g. it could be on yet another thread.

That leaves the issue of invoking custom key handlers which is probably a solvable problem but I don't recall the precise issues I hit.

@daxian-dbw
Copy link
Member

I cannot reproduce the issue on macOS with pwsh 7.0.0-preview.4 and PSReadLine 2.0.0-beta5.
*idle* shows up immediately after running the Register-EngineEvent command.
@nickcox Can you try 7.0.0-preview.4?

Oct-09-2019 13-40-02

@nickcox
Copy link
Author

nickcox commented Oct 9, 2019

👍Works for me on preview 4, @daxian-dbw

@nickcox
Copy link
Author

nickcox commented Oct 10, 2019

@daxian-dbw

On further investigation, it actually still isn't right. With preview 4 it seems to trigger the event exactly once.

Without PSReadLine

❯ pwsh -nologo -noprofile
PS /Users/nick.cox> Remove-Module PSReadline
PS /Users/nick.cox> $null = Register-EngineEvent -SourceIdentifier PowerShell.OnIdle -Action {Write-Host  '*idle*'} -MaxTriggerCount 3
PS /Users/nick.cox> *idle*
*idle*
*idle*

With PSReadLine

❯ pwsh -nologo -noprofile
PS /Users/nick.cox> Get-Module PSReadline
ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     2.0.0      PSReadLine                          {Get-PSReadLineKeyHandler, Get-PSReadLineOption, Remove-PSReadLineKeyHandler, Set-PSReadLineKeyHandler…}

PS /Users/nick.cox> $null = Register-EngineEvent -SourceIdentifier PowerShell.OnIdle -Action {Write-Host  '*idle*'} -MaxTriggerCount 3
PS /Users/nick.cox> *idle*
# ... (nothing happens until I press a key)
a*idle*
aa*idle*

@daxian-dbw daxian-dbw reopened this Oct 10, 2019
@daxian-dbw
Copy link
Member

Updated the repro steps.

@nickcox
Copy link
Author

nickcox commented Oct 10, 2019

Thanks. Should we update the environment data too then? Coz the updated repro steps don't correspond to what happens on the stated environment (PS version: 6.2.3).

@daxian-dbw
Copy link
Member

Of course, please update the environment data. Thanks

@SeeminglyScience
Copy link
Contributor

@daxian-dbw For context, dotnet/corefx#36049 made it occur less frequently, but anytime the cache is invalidated then the scenario I described will resurface.

@microsoft-github-policy-service
Copy link
Contributor

This issue is closed because it has had no activity and on older unsupported versions of PowerShell or PSReadLine. Please try again on latest versions of both and if its still an issue please submit a new issue.

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

No branches or pull requests

6 participants