-
Notifications
You must be signed in to change notification settings - Fork 44
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
Stop throwing an exception in the finally of WithTimeouts #563
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is If I'm likely not understanding something... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This was a fail safe to make sure it is working as I expected e.g. we throw so it doesn't matter that the timeouts were not reverted. I didn't want to swallow errors setting the timeouts when it was a real issue, e.g. the actual call has not thrown, but for some reason the set timeouts throws. That should never happen. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Should this happen? Is it valid? Will it leave us in a weird state if it did happen There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I see. The subtilty is that if we set the read/write timeout, and it throws a timeout exception, then this only really happens because it would have already thrown an exception with Yep, that makes sense 🙂 |
||
{ | ||
throw new InvalidOperationException("Could not revert the Timeouts. This should not happen."); | ||
} | ||
} | ||
|
||
|
@@ -40,17 +53,33 @@ public static async Task<T> WithTimeout<T>(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<Task> 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<T> WithReadTimeout<T>(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) | ||
|
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.
🤔 Just wondering, do other native .NET streams throw an exception when adjusting the Read/Write timeouts?
If not, then I wonder if an alternative would be to instead change the
NetworkTimeoutStream
to not throw an exception when changingReadTimeout
orWriteTimeout
.The current solution will be more generally safe, as it guarantees any read/write timeout alteration won't get in the way. But I couldn't help but wonder if we were guarding against something that shouldn't happen (and we got read/write timeout properties in
NetworkTimeoutStream
wrong instead).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.
It's up to the underlying stream and if it's a network stream, possibly the OS (maybe, I don't really know ;) )? I think they do throw if the stream is not usable, and you throw an unrelated, side effect error, hence why we wrapped it and rethrow the real error.
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.
If
NetworkTimeoutStream
doesn't throw, then do we risk getting into a situation where we swallow real errors and end up not correctly changing timeouts, but we think we have.