getsentry / getsentry/sentry-dotnet
Weird AsyncLocal behaviour in MAUI
- Dominant language
- C#
- Stars
- 770
- Forks
- 248
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 49
Description
## Problem
The `MauiCommunityToolkitMvvmEventsBinder` has some [code that wraps `AsyncRelayCommand` execution in a transaction]()... however it does something unexpected.
The first time this event triggers, there's no transaction on the scope and so a transaction gets created here.
Later, when the relay command finishes, the associated transaction is finished, which should reset the transaction on the scope (setting this to null):
[https://github.com/getsentry/sentry-dotnet/blob/8abc247566132a4b284d7fe24c44a93d84d32076/src/Sentry/TransactionTracer.cs#L399]()
And immediately after `span.Finish()` is called, this is the case (`scope.Transaction` has been reset).
However when the code runs for subsequent AsyncRelayCommands, for some reason the (completed) transaction is back on the scope again!
We created a [workaround in that PR]() but we really should dig into this to understand what's going on.
## Initial analysis
\_Originally posted by @jamescrosswell in [https://github.com/getsentry/sentry-dotnet/pull/4125#discussion_r2088443402\_]()
I don't quite understand what's happening yet, but most stuff on the Scope is global in MAUI cause we always set `IsGlobalMode = true` for MAUI apps. `Scope.Transaction` is an exception:
[https://github.com/getsentry/sentry-dotnet/blob/8abc247566132a4b284d7fe24c44a93d84d32076/src/Sentry/Scope.cs#L203]()
`AsyncLocal` has a [constructor overload]() that lets you wire up a ValueChanged event handler, which I did for `Scope._transaction` and there is definitely something very odd going on.
Putting a breakpoint in there, the first time it triggers is when our `OnPropertyChanged` fires, assigning `Scope.Transaction` for the first time (with the new transaction):

The it fires twice more with `args.ThreadContextChanged == true`:


Then it fires again from our `OnPropertyChanged` event handler when the command finishes running (this is finishing the transaction and resetting `Scope.Transaction = null`:

However immediately after that there's a thread context change again and the property gets restored to a non-null value!!! 🐛 🐞 😞

Contributor guide
Assessment
This issue has not been assessed yet.