-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
win,tty: fix read stop in line mode #866
Conversation
Who would have thought... |
@@ -483,7 +483,6 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); | |||
union { \ | |||
struct { \ | |||
/* Used for readable TTY handles */ \ | |||
HANDLE read_line_handle; \ |
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 this will break the ABI because the size of struct rd
is changed. Add a comment of it not being used anymore and we'll remove it for v2.
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.
Good call! Will fix.
Thanks a lot for working on this Alexis! I left some comments. There is one little important thing which definitely needs fixing: the ABI breakeage. Other than that, I don't have enough experience with low level Windows console handling to make a final judgement call, so I'll trust you and @piscisaureus. |
0cf4b49
to
ce8faac
Compare
Thanks for the feedback, @saghul ! I have added 3 commits to address your comments. I can fixup the original commits once the PR has passed review. |
LGTM if the CI is green: https://ci.nodejs.org/job/libuv-test-commit-windows/48/ But I'd like @piscisaureus to take a look too, if possible. |
it looks like the libuv CI is down... this is likely related to the updated that came in yesterday. /cc @jbergstroem |
I just noticed, thanks for taking a look Myles! |
To save anyone a trip to the console:
|
fingers crossed CI should be working now ci: https://ci.nodejs.org/view/libuv/job/libuv-test-commit-windows/51/ I will keep this comment updated with the status of getting this working to avoid spamming the thread |
Thanks Myles! Build is 💚 |
Closing the handle does not make ReadConsoleW exit reliably on Windows 7 and above. Thus, after switching from line to raw mode, keypresses were held until enter was pressed. This makes ReadConsoleW exit by writing a return keypress to its input buffer, similar to what was already done for raw mode. Fixes: libuv#852
ce8faac
to
c1cf6dc
Compare
Great, thanks! I applied the fixups, should be ready for landing. |
Can you please reword the second commit? Now we are not removing anything :-) I can work on a release tonight or on monday, but I guess nobody wants to release on a friday... |
@saghul we usually do the node releases on Tuesdays... so as long as it is out the door Monday I see no reason it could make it into next weeks v6 release |
Since we cancel ReadConsole by sending a newline, the duplicate handle is no longer necessary.
Thanks Alexis! @libuv/collaborators can I get another pair of eyes on this?
|
|
||
|
||
/* Null uv_buf_t */ | ||
static const uv_buf_t uv_null_buf_ = { 0, NULL }; | ||
|
||
static CRITICAL_SECTION uv__read_console_trap_lock; | ||
static volatile BOOL uv__read_console_trap = FALSE; |
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.
There is no need to mark these volatile.
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.
You are probably right, but in my (long, possibly dated) experience with VC++ it's safer to rely on explicit volatile declarations. It should be noted that the volatile semantics are MS-specific: https://msdn.microsoft.com/en-us/library/12a04hfd.aspx.
It's possible that the compiler has gotten smarter and knows not to reorder accesses around critical sections, but is there really much harm in making it explicit?
98548a0
to
edfb368
Compare
@piscisaureus, I updated the last commit to address most of your feedback. PTAL. I removed the wait from the main thread, and made the ReadConsole thread restore the console state. This should be safe and as you noted, it’s best not to have any waits in the main thread. I also added some logic to handle the simple scroll case. If the cursor was at the bottom of the screen buffer, then we can assume that the ENTER we sent caused the screen buffer to scroll up of one line, so we adjust accordingly. Note that I am not handling the case in which the screen buffer scrolled up of more than one line since we called GetConsoleScreenBufferInfo, which would be hard to detect and is hopefully very unlikely in practice. Even if we hit that case, we would end up with the cursor one line below where it should be, which should essentially have the same effect of the ENTER being visible. I also simplified the synchronization logic by using one status variable and interlocked operations. |
@piscisaureus I plan to release libuv with this fix (one you approve it) tonight, if you can get it reviewed by then it would be great. |
DWORD written; | ||
DWORD err = 0; | ||
LONG status; | ||
|
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.
assert(!(handle->flags & UV_HANDLE_CANCELLATION_PENDING))
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 can address this now
Great!
Sounds good to me.
First of all, good job, it's much cleaner this way. But it's a the fine line between diligent and nitpicky, and many users are clamoring for a fix. |
When we send VK_RETURN to make ReadConsole return, a spurious new line is echoed to the screen. This is pretty visible in Node.js, since it calls uv_tty_read_start() and uv_tty_read_stop() in rapid succession during startup. With this change, we save the screen state just before sending VK_RETURN, and restore the cursor position as soon as ReadConsole returns.
edfb368
to
5ad6688
Compare
Added the assert. |
One more CI run: https://ci.nodejs.org/job/libuv-test-commit-windows/57/ |
CI is 💚 and Bert gave us his blessing, so I'm landing this. |
Closing the handle does not make ReadConsoleW exit reliably on Windows 7 and above. Thus, after switching from line to raw mode, keypresses were held until enter was pressed. This makes ReadConsoleW exit by writing a return keypress to its input buffer, similar to what was already done for raw mode. Fixes: #852 PR-URL: #866 Reviewed-by: Bert Belder <bertbelder@gmail.com> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
Since we cancel ReadConsole by sending a newline, the duplicate handle is no longer necessary. PR-URL: #866 Reviewed-by: Bert Belder <bertbelder@gmail.com> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
When we send VK_RETURN to make ReadConsole return, a spurious new line is echoed to the screen. This is pretty visible in Node.js, since it calls uv_tty_read_start() and uv_tty_read_stop() in rapid succession during startup. With this change, we save the screen state just before sending VK_RETURN, and restore the cursor position as soon as ReadConsole returns. PR-URL: #866 Reviewed-by: Bert Belder <bertbelder@gmail.com> Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
Awesome! Thanks a lot for the reviews and all the help, @saghul and @piscisaureus ! |
Closing the handle does not make
ReadConsoleW
exit reliably on Windows 7 and above. Thus, after switching from line to raw mode, keypresses were held until enter was pressed. This has caused a number of issues in node: nodejs/node#2504 , nodejs/node#2996, nodejs/node#5384 , nodejs/node#5821 , nodejs/node#5940 .This fix makes
ReadConsoleW
exit by writing a return keypress to its input buffer, similar to what was already done for raw mode. The second commit removes the duplicate handle that was used to close the console before. The third commit restores the cursor position to where it was before writing the enter, becauseReadConsoleW
echoes the newline in the screen.This PR includes a test that switches the console to raw mode and uses
WriteConsoleInputW
to test reading in raw mode. I do not know of a unix equivalent toWriteConsoleInputW
, so the test is for Windows only. In this test, switching to raw mode is done after a 100 ms sleep, to allowuv_tty_line_read_thread
to reachReadConsoleW
.The added
User32
library is necessary forMapVirtualKeyW
.Fixes: #852
cc @saghul @piscisaureus