realm / realm-dotnet

Realm is a mobile database: a replacement for SQLite & ORMs
https://realm.io
Apache License 2.0
1.24k stars 161 forks source link

[Bug]: await LogInAsync(Credentials.Anonymous) always hangs the first time app runs #3090

Closed winnicki closed 1 year ago

winnicki commented 1 year ago

What happened?

The first time I install and run the app, var user = await _realmApp.LogInAsync(Credentials.Anonymous()); always hangs. No output or exceptions. I can always reproduce and I've done so on multiple simulators and devices. I'm not doing anything special of weird with threading and it always works the second time I run the app.

I have a simple Xamarin sandbox app that I'm using for testing Realm. I can invite you to the GitHub repo if you give me an email. It will compile and run with no problems.

Repro steps

  1. Install and run the app for the first time
  2. Put a breakpoint on LoginAsync and another on the next line

Result: App hangs. Need to re-run it and the second time it won't hang.

Version

10.18.0 but I can also repro on 10.17.0

What SDK flavour are you using?

MongoDB Atlas (i.e. Sync, auth, functions)

What type of application is this?

Xamarin

Client OS and version

iOS 16 but I saw it on previous versions (15 for sure.. I don't expect it's iOS related)

Code snippets

Once I give you access to my repo you can break on the LoginAsync call in FolderClientService.

Stacktrace of the exception/crash you're getting

It just hangs unfortunately.

Relevant log output

No response

nirinchev commented 1 year ago

Hey, can you send me an invite at irinchev@me.com?

winnicki commented 1 year ago

Done

winnicki commented 1 year ago

@nirinchev I forgot to mention that you'll want to run master branch. Thanks!

nirinchev commented 1 year ago

Okay, I'm not an expert in Mvx, so I don't know where the problem is, but it seems there's some sort of a deadlock - as soon as you do anything async in FolderViewModel.Initialize, the app hangs. You can reproduce this by adding a Task.Delay that will cause the app to always hang. I've put up a PR that you can checkout and verify this: https://github.com/winnicki/RealmDev/pull/1. As such, I don't believe it's a problem with Realm, but rather a problem with the way the view model lifecycle is wired up. My guess is that something is blocking the UI thread until Initialize completes, but it cannot complete because it needs to schedule the continuation of the task back on the UI thread.

My guess is that this is also the reason for GetInstanceAsync hanging. Once you've resolved these issues, we can see if the ArgumentOutOfRange error goes away or it's still there.

Note that due to Realm's threading model, it's important that the Realm instance is opened on the same thread it's going to be used on. So while you can do ConfigureAwait(false) on the login call to have it continue off the main thread, it's important that the Realm instance is opened on the UI thread if you're going to be interacting with it from the UI thread.

winnicki commented 1 year ago

@nirinchev Good idea with the Task.Delay, I should've thought of that. It's curious that it works on the second run so that's why I ruled out Mvx, but what you're saying makes sense. Like you said, I wouldn't be surprised if the other issues are resolved after I fix this one.

Thanks for your time. I'll come back tonight and try to close these 3 issues.

nirinchev commented 1 year ago

No worries! The reason why it works on the second run is that at this point the call is synchronous - the first time you authenticate, we persist the user locally, so the second time, we see that we have a user and return that without actually calling the server.

If you want to take advantage of that, you can use app.CurrentUser to access previously logged-in users without having to reauthenticate. This is done automatically for anonymous users, but will not work for other credential types as we don't persist the actual credential out of security considerations.

winnicki commented 1 year ago

This clears up everything now, thanks :).

winnicki commented 1 year ago

@nirinchev Closing this and the other issues. I'm running my init logic when the view appeared and it doesn't hang + the other methods work as expected. It's something with Mvx for sure. Thanks again.