From e5537d814bb460c3d6736e43fbf2da7f21fff162 Mon Sep 17 00:00:00 2001 From: Dan Thompson Date: Thu, 27 Jul 2023 11:47:06 -0700 Subject: [PATCH] Work around `InvalidOperationException` from Console API (#3755) --- PSReadLine/ConsoleLib.cs | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/PSReadLine/ConsoleLib.cs b/PSReadLine/ConsoleLib.cs index 7cc53b341..dc1d1b455 100644 --- a/PSReadLine/ConsoleLib.cs +++ b/PSReadLine/ConsoleLib.cs @@ -113,8 +113,40 @@ public Encoding OutputEncoding set { try { Console.OutputEncoding = value; } catch { } } } - public ConsoleKeyInfo ReadKey() => _readKeyMethod.Value(true); - public bool KeyAvailable => Console.KeyAvailable; + private static T _TryIgnoreIOE(Func f) + { + int triesLeft = 10; + while (true) + { + try + { + triesLeft--; + return f(); + } + catch (InvalidOperationException) + { + // Ignore it. An IOE could be thrown if the "application does not have a + // console or when console input has been redirected"... but we don't + // expect PSReadLine to be involved in such a situation. So we are + // actually probably running into this Issue (wherein another process + // attached to the same console terminated at just the right/wrong time): + // + // https://github.com/dotnet/runtime/issues/88697 + // + // In the event there is some *other* pathological situation + // happening, we have limited the number of times we will + // swallow/retry this exception/operation. + + if (triesLeft <= 0) + { + throw; + } + } + } + } + + public ConsoleKeyInfo ReadKey() => _TryIgnoreIOE(() => _readKeyMethod.Value(true)); + public bool KeyAvailable => _TryIgnoreIOE(() => Console.KeyAvailable); public void SetWindowPosition(int left, int top) => Console.SetWindowPosition(left, top); public void SetCursorPosition(int left, int top) => Console.SetCursorPosition(left, top); public virtual void Write(string value) => Console.Write(value);