-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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]: Let accessing the instance of Exception (if any) on stack. #89724
Comments
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsBackground and motivationFrom time to time there's a need to not only check whether stack contains a bubbling up exception, but also to get access to the exception itself. For example, in Open Telemetry library However, if I don't want `OperationCancelledException' to be treated as an error, I need to have access to the instance of the exception thrown. Currently, there's no such possibility. API ProposalWell, I am not familiar with the intricacies of CLR, and whether such API is conceptually possible, but something like adding property to
API Usagetry
{
throw new Exception();
}
finally
{
// Here it is not null;
Console.WriteLine(AppDomain.CurrentDomain.CurrentException is not null);
} try
{
throw new Exception();
}
catch
{
// Here it is null;
Console.WriteLine(AppDomain.CurrentDomain.CurrentException is null);
}
finally
{
// Here it is null;
Console.WriteLine(AppDomain.CurrentDomain.CurrentException is null);
} try
{
throw new Exception();
}
catch
{
// Here it is null;
Console.WriteLine(AppDomain.CurrentDomain.CurrentException is null);
throw;
}
finally
{
// Here it is not null;
Console.WriteLine(AppDomain.CurrentDomain.CurrentException is not null);
} Not sure whether value should propagate with async. Task CheckMe() => Task.Run(() => Console.WriteLine(AppDomain.CurrentDomain.CurrentException is not null));
try
{
throw new Exception();
}
finally
{
// Here it is not null;
Console.WriteLine(AppDomain.CurrentDomain.CurrentException is not null);
// will it output true or false?
await CheckMe();
// Here it is not null;
Console.WriteLine(AppDomain.CurrentDomain.CurrentException is not null);
}
|
Could Open Telemetry achieve the same result using a first-chance exception handler? |
If I am not missing something particularly important, it should work.
|
@voroninp I would change But I'm no expert, so no promises this works without extensive testing. 😅 |
I started with Weak reference, but decided, GCHandle will prevent memory allocations. |
I ended up with the implementation below. Do you see any possible issues with it? public sealed class DetailedExceptionProcessor : BaseProcessor<Activity>
{
private const string EnabledKey = "DetailedExceptionProcessor.Enabled";
private const string ExceptionKey = "DetailedExceptionProcessor.Exception";
static DetailedExceptionProcessor()
{
AppDomain.CurrentDomain.FirstChanceException += (_, args) =>
{
if (Activity.Current is { } activity
&& activity.GetCustomProperty(EnabledKey) is true)
{
activity.SetCustomProperty(ExceptionKey, args.Exception);
}
};
}
public override void OnStart(Activity activity)
{
activity.SetCustomProperty(EnabledKey, true);
}
public override void OnEnd(Activity activity)
{
if (activity.GetCustomProperty(ExceptionKey) is Exception exception
&& Marshal.GetExceptionPointers() != IntPtr.Zero)
{
activity.SetStatus(Status.Error);
activity.RecordException(exception);
activity.SetStatus(ActivityStatusCode.Error);
}
activity.SetCustomProperty(EnabledKey, null);
activity.SetCustomProperty(ExceptionKey, null);
}
} |
Yep came up to similar one https://gist.github.com/voroninp/704c1cb556bd03697ef0c80524de1b24 |
This will leak the GCHandles over time as threads come and go. There is nothing that would take care of cleaning up of the GCHandles - GCHandles are low-level "unmanaged" resources that must be freed manually. |
@jkotas , despite it allocation with weak type?! |
This will capture the last thrown exception. It won't be the exception that the activity crashed with if there are exceptions thrown and handled during cleanup (finally blocks, |
Yes, the weak type for GCHandle means that the target is referenced weekly. It does change that the GCHandle itself must be explicitly freed. You want to use |
@jkotas , thanks, I'll fix it. |
Background and motivation
From time to time there's a need to not only check whether stack contains a bubbling up exception, but also to get access to the exception itself.
For example, in Open Telemetry library
ExceptionProcessor
usesMarshal.GetExceptionPointers
to check whether exception is thrown withing the scope of activity.However, if I don't want `OperationCancelledException' to be treated as an error, I need to have access to the instance of the exception thrown. Currently, there's no such possibility.
API Proposal
Well, I am not familiar with the intricacies of CLR, and whether such API is conceptually possible, but something like adding property to
AppDomain
could work:throw
should set this property (overwriting previous value),catch
with matching exception should set it tonull
.API Usage
Not sure whether value should propagate with async.
The text was updated successfully, but these errors were encountered: