Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit a844c92

Browse files
authored
Port 'Delay console CPR timer once protocol has worked' to 2.1 (#30759)
1 parent fd29f78 commit a844c92

File tree

1 file changed

+19
-1
lines changed

1 file changed

+19
-1
lines changed

src/System.Console/src/System/ConsolePal.Unix.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,13 @@ public static int CursorTop
332332
}
333333
}
334334

335+
/// <summary>
336+
/// Tracks whether we've ever successfully received a response to a cursor position request (CPR).
337+
/// If we have, then we can be more aggressive about expecting a response to subsequent requests,
338+
/// e.g. using a longer timeout.
339+
/// </summary>
340+
private static bool s_everReceivedCursorPositionResponse;
341+
335342
/// <summary>Gets the current cursor position. This involves both writing to stdout and reading stdin.</summary>
336343
private static unsafe void GetCursorPosition(out int left, out int top)
337344
{
@@ -358,7 +365,15 @@ private static unsafe void GetCursorPosition(out int left, out int top)
358365
// one thread's get_CursorLeft/Top from providing input to the other's Console.Read*.
359366
lock (StdInReader)
360367
{
361-
Interop.Sys.InitializeConsoleBeforeRead(minChars: 0, decisecondsTimeout: 10);
368+
// Because the CPR request/response protocol involves blocking until we get a certain
369+
// response from the terminal, we want to avoid doing so if we don't know the terminal
370+
// will definitely response. As such, we start with minChars == 0, which causes the
371+
// terminal's read timer to start immediately. Once we've received a response for
372+
// a request such that we know the terminal supports the protocol, we then specify
373+
// minChars == 1. With that, the timer won't start until the first character is
374+
// received. This makes the mechanism more reliable when there are high latencies
375+
// involved in reading/writing, such as when accessing a remote system.
376+
Interop.Sys.InitializeConsoleBeforeRead(minChars: (byte)(s_everReceivedCursorPositionResponse ? 1 : 0), decisecondsTimeout: 10);
362377
try
363378
{
364379
// Write out the cursor position report request.
@@ -425,6 +440,9 @@ private static unsafe void GetCursorPosition(out int left, out int top)
425440
// else back into the StdInReader.
426441
ReadRowOrCol(bracketPos, semiPos, r, readBytes, ref top);
427442
ReadRowOrCol(semiPos, rPos, r, readBytes, ref left);
443+
444+
// Mark that we've successfully received a CPR response at least once.
445+
s_everReceivedCursorPositionResponse = true;
428446
}
429447
finally
430448
{

0 commit comments

Comments
 (0)