-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Audit System.Net throws losing stack traces #16898
Conversation
There are a bunch of places throughout the System.Net libraries where exceptions are captured and later thrown, using `throw e;`. This overwrites their stack trace and bucket information, making it harder to diagnose problems when they occur. Over time we've chipped away at these, so there are many fewer now than there used to be, but some still remain. I've audited all of the System.Net libs, and fixed all the locations I found where this pattern was being employed, replacing them with usage of ExceptionDispatchInfo to avoid losing the call stack data. There are still some `throw e`s I left, but those were typically of a form where it was obvious no data would be lost, e.g. the exception was just instantiated a few lines earlier. There are likely also a few straggling cases, e.g. where `throw SomeFunction()` is used and `SomeFunction()` returns a cached exception instance, but we can address those on a case-by-case basis as we find them.
Why don't we have public static class ExceptionExtensions
{
public static void Rethrow(this Exception exception)
{
ExceptionDispatchInfo.Capture(exception).Throw();
}
} |
|
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.
Thanks Stephen. This is going to make life a lot easier for a few people :)
@@ -641,7 +642,7 @@ private static void SendEHelloCallback(IAsyncResult result) | |||
if ((e.StatusCode != SmtpStatusCode.CommandUnrecognized) | |||
&& (e.StatusCode != SmtpStatusCode.CommandNotImplemented)) | |||
{ | |||
throw e; | |||
throw; |
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.
throw
retains the information but not throw e
? Why don't we need the Capture/Throw here?
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.
Right. throw;
can only be used inside of a catch
block, and effectively continues the propagation of the exception that was caught (kind of like catch-and-release'ing a fish), so it retains its original info. throw e;
can be done anywhere, and overwrites the info.
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.
gotcha, thanks for the explanation.
Yes, this is a very self-serving change 😉 |
…on_throws Audit System.Net throws losing stack traces Commit migrated from dotnet/corefx@70114fe
There are a bunch of places throughout the System.Net libraries where exceptions are captured and later thrown, using
throw e;
. This overwrites their stack trace and bucket information, making it harder to diagnose problems when they occur. Over time we've chipped away at these, so there are many fewer now than there used to be, but some still remain.I've audited all of the System.Net libs, and fixed all the locations I found where this pattern was being employed, replacing them with usage of ExceptionDispatchInfo to avoid losing the call stack data. There are still some
throw e
s I left, but those were typically of a form where it was obvious no data would be lost, e.g. the exception was just instantiated a few lines earlier. There are likely also a few straggling cases, e.g. wherethrow SomeFunction()
is used andSomeFunction()
returns a cached exception instance, but we can address those on a case-by-case basis as we find them.Fixes https://github.com/dotnet/corefx/issues/5606
cc: @geoffkizer, @CIPop, @davidsh, @Priya91