-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
API Proposal: ExceptionDispatchInfo.TrySetStackTrace #50044
Comments
Where do we expect this to be called on exceptions that have a stacktrace set already? Why not throw like what |
@jkotas I don't feel strongly one way or the other on this. If there's a way for a caller to detect likely failure ahead of time (query Exception.StackTrace and see if it's populated?), then the try pattern doesn't add much. |
Just to make sure I understand the proposed semantics, SetCurrentStackTrace would then be logically equivalent to: return SetStackTraceString(exception, GetCurrentStackTrace()); ? |
Basically, yeah. I suppose |
namespace System.Runtime.ExceptionServices
{
public sealed class ExceptionDispatchInfo
{
public static void SetRemoteStackTrace(Exception source, string stackTrace);
// existing API for reference
// public static Exception SetCurrentStackTrace(Exception source);
}
} Edit I've replaced |
I verified the "arbitrary string" behavior in two ways. First, I called
(The I also verified the behavior of As far as I can tell this means we should be good to go. |
But does |
Not for the |
Scenario
One of the primary uses of
BinaryFormatter
is to serializeException
objects. Since we are obsoleting this serializer, we need to investigate new ways of serializing exception data.For most
Exception
-derived types, serializers can be written to call the applicable public ctor based on parameter name (forArgumentException
), HRESULT, exception text, and inner exception object. However, one big omission is the ability to set the stack trace on a newly-constructed, unthrown Exception instance. Without this, "safe"Exception
serializers and deserializers cannot reproduce the initial exception object with a high enough fidelity to allow for debugging.Proposed API
Usage
Behavior and discussion
The method requires non-null
Exception
andstring
arguments. If the exception instance has been previously thrown or already has an associated stack trace, the method has no effect and returns false. (ExceptionDispatchInfo.SetCurrentStackTrace
would throw in this scenario.) If the exception instance is an immutable or singleton exception, the method has no effect and returns false. (ExceptionDispatchInfo.SetCurrentStackTrace
would no-op in this scenario.) Otherwise theException.StackTrace
property is set to the provided string value and this method returns true.No validation is performed over the contents or shape of the provided string. It is completely opaque to the runtime.
The
Exception.TargetSite
property will remain null after the stack trace string has been set. The runtime will not attempt to parse the stack trace string and recover the originalMethodBase
object. Additionally, the exception object's Watson bucket data will remain unpopulated. This behavior is to support the ideas that: (a) the stack trace might be provided by an untrustworthy source and thus must not be run through the reflection APIs; and (b) the stack trace might refer to an assembly not available to the current process.Alternative designs
We could require capturing the exception within the
EDI
before allowing setting the stack trace string. This may even allow us to overwrite the stack trace string from a previously-thrown exception. Doing this would also promote the idea of "this is meant for the purpose of restoring a stack trace from ancillary data before re-throwing the exception" as a first-class concept, even above vanilla deserialization. (The deserialization-without-rethrowing scenario would still be achieveable; simply check theExceptionDispatchInfo.SourceException
property instead of rethrowing it.)However, the existing
SetCurrentStackTrace
method does not require anEDI
wrapper, so for symmetry the main proposal above also does not require the existence of anEDI
wrapper.We could also consider adding a method
SetStackTrace
directly to theException
object. However, I believe this will encourage misuse of what is supposed to be a specialized API. Putting this new API on theEDI
class makes it a proper sibling of the existingSetCurrentStackTrace
API, which further helps symmetry.>> Marked partner blocking (/cc @ReubenBond)
The text was updated successfully, but these errors were encountered: