From d51fce985879026aec20eb9977b13086171fba9d Mon Sep 17 00:00:00 2001 From: Nathan Willoughby Date: Thu, 30 Nov 2023 12:35:54 +1000 Subject: [PATCH] Fix an issue with WithTimeouts where the finally can fail if hte stream is in an error state and potentially hide / rethrow the original error causing confusion about the source of the error. --- .../Protocol/StreamTimeoutExtensionMethods.cs | 74 +++++++++++++++++-- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/source/Halibut/Transport/Protocol/StreamTimeoutExtensionMethods.cs b/source/Halibut/Transport/Protocol/StreamTimeoutExtensionMethods.cs index d86fde3f..54b2c4ae 100644 --- a/source/Halibut/Transport/Protocol/StreamTimeoutExtensionMethods.cs +++ b/source/Halibut/Transport/Protocol/StreamTimeoutExtensionMethods.cs @@ -18,6 +18,7 @@ public static async Task WithTimeout(this Stream stream, SendReceiveTimeout? tim var currentReadTimeout = stream.ReadTimeout; var currentWriteTimeout = stream.WriteTimeout; + var timeoutsReverted = false; try { @@ -26,8 +27,20 @@ public static async Task WithTimeout(this Stream stream, SendReceiveTimeout? tim } finally { - stream.ReadTimeout = currentReadTimeout; - stream.WriteTimeout = currentWriteTimeout; + try + { + stream.ReadTimeout = currentReadTimeout; + stream.WriteTimeout = currentWriteTimeout; + timeoutsReverted = true; + } + catch + { + } + } + + if (!timeoutsReverted) + { + throw new InvalidOperationException("Could not revert the Timeouts. This should not happen."); } } @@ -40,17 +53,33 @@ public static async Task WithTimeout(this Stream stream, SendReceiveTimeou var currentReadTimeout = stream.ReadTimeout; var currentWriteTimeout = stream.WriteTimeout; + var timeoutsReverted = false; + T result; try { stream.SetReadAndWriteTimeouts(timeout); - return await func(); + result = await func(); } finally { - stream.ReadTimeout = currentReadTimeout; - stream.WriteTimeout = currentWriteTimeout; + try + { + stream.ReadTimeout = currentReadTimeout; + stream.WriteTimeout = currentWriteTimeout; + timeoutsReverted = true; + } + catch + { + } } + + if (!timeoutsReverted) + { + throw new InvalidOperationException("Could not revert the Timeouts. This should not happen."); + } + + return result; } public static async Task WithReadTimeout(this Stream stream, TimeSpan timeout, Func func) @@ -63,6 +92,7 @@ public static async Task WithReadTimeout(this Stream stream, TimeSpan timeout, F } var currentReadTimeout = stream.ReadTimeout; + var timeoutsReverted = false; try { @@ -71,7 +101,19 @@ public static async Task WithReadTimeout(this Stream stream, TimeSpan timeout, F } finally { - stream.ReadTimeout = currentReadTimeout; + try + { + stream.ReadTimeout = currentReadTimeout; + timeoutsReverted = true; + } + catch + { + } + } + + if (!timeoutsReverted) + { + throw new InvalidOperationException("Could not revert the Timeouts. This should not happen."); } } @@ -83,16 +125,32 @@ public static async Task WithReadTimeout(this Stream stream, TimeSpan time } var currentReadTimeout = stream.ReadTimeout; + var timeoutsReverted = false; + T result; try { stream.SetReadTimeouts(timeout); - return await func(); + result = await func(); } finally { - stream.ReadTimeout = currentReadTimeout; + try + { + stream.ReadTimeout = currentReadTimeout; + timeoutsReverted = true; + } + catch + { + } } + + if (!timeoutsReverted) + { + throw new InvalidOperationException("Could not revert the Timeouts. This should not happen."); + } + + return result; } public static void SetReadAndWriteTimeouts(this Stream stream, SendReceiveTimeout? timeout)