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
❯ 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*
❯ 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*
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.
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:
❯ 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.
❯ 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).
@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?
@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.
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.
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.
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.
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
?
👍Works for me on preview 4, @daxian-dbw
@daxian-dbw
On further investigation, it actually still isn't right. With preview 4 it seems to trigger the event exactly once.
❯ 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*
❯ 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*
Updated the repro steps.
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
).
Of course, please update the environment data. Thanks
@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.