-
Notifications
You must be signed in to change notification settings - Fork 751
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
Deadlock on OSX #1092
Comments
Is there a code that blocks or locks? Can you check who is doing what when there is a deadlock? Could you try with System.Reactive 4.2.0? Also your project looks complicated for someone outside of it to track things down. Could you create a minimal project that shows the hang issue? |
No, it just rebuilds the CoinList. No locks or blocks.
Upgraded, it hangs too.
Yes, I can but it is not easy because I am using reactive through Avalonia and maybe that causes the problem. Just by looking at this ViewModel everything seems legit there? |
Rx' FromEventPattern is not thread safe by itself and can cause arbitrary bugs down the stream. If your events can come from any thread, it's possible something will break. Try applying |
Hmm, that makes sense. By Synchronize you thought about this? I added the UI thread |
No, Synchronize(). Individual sources can't be driven concurrently. FromEventPattern uses a Subject to dispatch and the scheduler version is just like applying |
Observable
.Merge(Observable.FromEventPattern(this, nameof(CoinListChanged)).Select(_ => Unit.Default))
.Throttle(TimeSpan.FromSeconds(2)) // Throttle TransactionProcessor events adds/removes.
.Merge(Observable.FromEventPattern(this, nameof(CoinListShown)).Select(_ => Unit.Default)) // Load the list immediately.
.ObserveOn(RxApp.MainThreadScheduler) The subscription to C# events is usally not thread safe, hence you have to be careful where the event subscription happens. BTW I see that you are using |
So I did this and looks like the situation improved. I added Observable
.Merge(Observable.FromEventPattern<ReplaceTransactionReceivedEventArgs>(Global.WalletService.TransactionProcessor, nameof(Global.WalletService.TransactionProcessor.ReplaceTransactionReceived)).Select(_ => Unit.Default).Synchronize())
.Merge(Observable.FromEventPattern<DoubleSpendReceivedEventArgs>(Global.WalletService.TransactionProcessor, nameof(Global.WalletService.TransactionProcessor.DoubleSpendReceived)).Select(_ => Unit.Default).Synchronize())
.Merge(Observable.FromEventPattern<SmartCoin>(Global.WalletService.TransactionProcessor, nameof(Global.WalletService.TransactionProcessor.CoinSpent)).Select(_ => Unit.Default).Synchronize())
.Merge(Observable.FromEventPattern<SmartCoin>(Global.WalletService.TransactionProcessor, nameof(Global.WalletService.TransactionProcessor.CoinReceived)).Select(_ => Unit.Default).Synchronize())
.Subscribe(args =>
{
try
{
OnCoinListChanged();
}
catch (Exception ex)
{
Logger.LogError(ex);
}
})
.DisposeWith(Disposables); As far as I can understand I do not need to sync events from different sources but I have to sync events from the same source. So there is no need to create an |
Thank you for your help @akarnokd and @quinmars. I solved the problem. I elaborated on the problem and a deeper I went the dirtier it became but anyway: The first one is to use The second problem was with Useful articles: |
Hi there,
I am refactoring our CoinListViewModel in WasabiWallet. It works fine on Windows and Linux but on OSX it hangs randomly. I have no clue it might be Reactive so I decided to ask you guys.
Environment:
Stack trace
The UI gets unresponsible and when I pause the execution it stands here:
https://github.com/zkSNACKs/WalletWasabi/pull/2602/files#diff-8ef0b233124cda8dfcef1707a9d8df4aR598
Called from here:
https://github.com/zkSNACKs/WalletWasabi/pull/2602/files#diff-8ef0b233124cda8dfcef1707a9d8df4aR462
Sometimes it hangs here too: https://github.com/zkSNACKs/WalletWasabi/pull/2602/files#diff-8ef0b233124cda8dfcef1707a9d8df4aR593
Purpose of the code
Instead of refreshing the CoinList every time when there is a change I created an event
CoinListChanged
. I am calling this event from several places and throttle it - so the list will be refreshed only once.Hacky solution
If I replace this line:
CoinListChanged?.Invoke(this, null);
with
Task.Run(() => CoinListChanged?.Invoke(this, null));
It will work.
Theory
ThreadPool randomly selects the executor Thread for the tasks. If it selects the same thread which should run the task it will wait for itself forever. Or there is some circular waiting list that is not detected on OSX. I also noticed the same behavior when I used the
Subscribe
withWhenAnyValue
and modify the same value inside the subscription - it also hangs randomly on OSX at the line: set =>this.RaiseAndSetIfChanged
.This is a long-running issue in Wasabi and I always hacked it around which is not a long term solution, any suggestion appreciated.
The text was updated successfully, but these errors were encountered: