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

Audit System.Net throws losing stack traces #16898

Merged
merged 1 commit into from
Mar 10, 2017

Conversation

stephentoub
Copy link
Member

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 es 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.

Fixes https://github.com/dotnet/corefx/issues/5606
cc: @geoffkizer, @CIPop, @davidsh, @Priya91

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.
@danmoseley
Copy link
Member

Why don't we have

     public static class ExceptionExtensions
     {
        public static void Rethrow(this Exception exception)
         {
             ExceptionDispatchInfo.Capture(exception).Throw();
         }
     }

@stephentoub
Copy link
Member Author

Why don't we have...

https://github.com/dotnet/corefx/issues/16896

Copy link
Contributor

@ianhays ianhays left a 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;
Copy link
Contributor

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?

Copy link
Member Author

@stephentoub stephentoub Mar 9, 2017

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.

Copy link
Contributor

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.

@stephentoub
Copy link
Member Author

stephentoub commented Mar 9, 2017

This is going to make life a lot easier for a few people :)

Yes, this is a very self-serving change 😉

@stephentoub stephentoub merged commit 70114fe into dotnet:master Mar 10, 2017
@stephentoub stephentoub deleted the audit_exception_throws branch March 10, 2017 04:51
@karelz karelz modified the milestone: 2.0.0 Mar 10, 2017
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
…on_throws

Audit System.Net throws losing stack traces

Commit migrated from dotnet/corefx@70114fe
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

System.Net: Replace existing "catch Exception / throw later" patterns with ExceptionDispatchInfo
6 participants