realm / realm-core

Core database component for the Realm Mobile Database SDKs
https://realm.io
Apache License 2.0
1.02k stars 165 forks source link

Multiprocess issue on windows #4189

Closed sync-by-unito[bot] closed 3 years ago

sync-by-unito[bot] commented 3 years ago

On Windows, writing from multiple processes while simultaneously listening for notifications causes something to lock up preventing the Realm from refreshing/delivering notifications.

Here's a simple app that reproduces the issue after 3-4 instances of it are run:

using System;
using System.Linq;
using System.Threading.Tasks;
using Nito.AsyncEx;
using Realms;

namespace SimpleRealmWriter
{
    internal class Program
    {
        private const string RealmLocation = "C:\\Work\\example.realm";

        private static void Main(string[] args)
        {
            AsyncContext.Run(async () =>
            {
                var realm = Realm.GetInstance(RealmLocation);
                var counter = realm.All<MyCounter>().FirstOrDefault();
                if (counter == null)
                {
                    counter = new MyCounter();
                    realm.Write(() => realm.Add(counter));
                }
                counter.PropertyChanged += (s, e) =>
                {
                    Console.WriteLine($"Counter's {e.PropertyName} changed: {counter.Value}");
                };

                while (true)
                {
                    await Task.Delay(1000);
                    var tsr = ThreadSafeReference.Create(counter);
                    await Task.Run(() =>
                    {
                        using var bgRealm = Realm.GetInstance(RealmLocation);
                        var bgCounter = bgRealm.ResolveReference(tsr);
                        bgRealm.Write(() =>
                        {
                            bgCounter.Value++;
                        });
                    });

                    realm.Refresh(); // Locks up here

                    Console.WriteLine($"Counter: {counter.Value}");
                }
            });
        }
    }

    internal class MyCounter : RealmObject
    {
        public int Value { get; set; }
    }
}
sync-by-unito[bot] commented 3 years ago

➤ On 2019-11-26, Nikola Irinchev commented:

@fealebenpae assigning you to do a sanity check of my code and confirm I'm not doing something obviously stupid. I don't think it's a super high priority issue, but just confirming that it's a bug would be a good start.

sync-by-unito[bot] commented 3 years ago

➤ On 2019-11-26, chrisk414 commented:

Hi, guys! Thanks for looking into this bug. I'm currently stuck at this and it's important for my project that more than one client can work on the same local realm.

From my testing, the thread lock problem happens while more than two clients are trying to write, notify changes and/or quit. I hope they are all related to the same bug. I'll be more than happy to test for different scenarios.

As a side note, I'm using Realm.dll (Local DB version), the version you get pulling off of Realm.Database NuGet. There is a reason why I'm using the local version instead of the networkable version. And I will really appreciate it if the fixes are made to both versions.

Cheers!

sync-by-unito[bot] commented 3 years ago

➤ On 2019-11-26, chrisk414 commented:

Hey guys, any update on this? To me, locking is a critical bug. Thanks for taking a look.

sync-by-unito[bot] commented 3 years ago

➤ On 2019-12-09, chrisk414 commented:

Hi guys, any progress being made on this issue? Thanks.

sync-by-unito[bot] commented 3 years ago

➤ On 2020-01-01, chrisk414 commented:

Happy new year guys! I'm still waiting if this has been fixed in the upcoming release. Please let me know as this is a show stopper for me. Thanks

sync-by-unito[bot] commented 3 years ago

➤ On 2020-01-02, Yavor Georgiev commented:

Hey @chrisk414, unfortunately we haven't been able to address this issue so far. It's something we've seen happen for a while but we haven't been able to come up with a fix.

sync-by-unito[bot] commented 3 years ago

➤ On 2020-01-02, chrisk414 commented:

Hi, Is there anyone who is actively looking at this? This is easily reproducable for anyone using it and I think it's pretty critical. Thanks.

sync-by-unito[bot] commented 3 years ago

➤ On 2020-01-02, Nikola Irinchev commented:

I'd like to clarify that this is not very high priority because a very small percentage of our users are affected by it. The majority of our users ship Android/iOS apps where the issue doesn't exist. Then, for those that ship windows apps, they'll have to write to the same realm from multiple processes which is not a common scenario. So while I understand it's critical for you and your use case, the unfortunate reality is that we have tasks that will benefit far more people that we'd like to address first.

sync-by-unito[bot] commented 3 years ago

➤ On 2020-01-07, chrisk414 commented:

Right, thanks for making clear after a couple of months of the wait. Perhaps you should make it clear about the warning that it's not for .Net then. Is that going to be your stance in the future too? Regardless of how many users are using .Net, the severity of this problem is severe and there is no workaround. I see a similar bug about the deadlock above and I'm not alone.

sync-by-unito[bot] commented 3 years ago

➤ On 2020-01-07, Nikola Irinchev commented:

I already mentioned it's not a super high priority issue in my comment ( https://github.com/realm/realm-object-store/issues/872#issuecomment-551269592 ) immediately after filing it. As I said, the number of users affected by this issue is very small compared to the number of people using the .NET SDK (as most of them write Xamarin apps and this issue is windows-specific). Our stance will always be that we'll prioritize issues based on the number of people affected or the severity of the issue. If we suddenly get swarmed by people complaining about this problem, we'll obviously bump the priority.

sync-by-unito[bot] commented 3 years ago

➤ On 2020-01-08, chrisk414 commented:

Thanks. I'll wait for it then and I hope it lands before the final 6.0 release. Cheers!

sync-by-unito[bot] commented 3 years ago

➤ On 2020-09-21, Dean Herbert commented:

This is a pretty major blocker for our potential uptake of Realm as a replacement for EF-core. The only way to avoid this bug is to not use notification subscription at all, which severely limits how we can interact with realm in an asynchronous way.

Any chance of this getting attention within the near future? Thanks!

sync-by-unito[bot] commented 3 years ago

➤ On 2020-11-20, Nikola Irinchev commented:

I tried running the repro case with the fix in https://github.com/realm/realm-object-store/pull/1142. The bad news are that it doesn't appear to resolve the problem. I distilled a simpler test case and ran that:

Simpler test case using System; using System.Linq; using System.Threading.Tasks; using Nito.AsyncEx; using Realms; namespace SimpleRealmWriter { internal class Program { private const string RealmLocation = "C:\Work\example.realm"; private static void Main(string[ ] args) { AsyncContext.Run(async () => { var realm = Realm.GetInstance(RealmLocation); var counter = realm.All().FirstOrDefault(); if (counter == null) { counter = new MyCounter(); realm.Write(() => realm.Add(counter)); } counter.PropertyChanged += (s, e) => { Console.WriteLine($"Counter's {e.PropertyName} changed: {counter.Value}"); }; while (true) { await Task.Delay(1000); realm.Write(() => { counter.Value++; }); //realm.Refresh(); // Locks up here Console.WriteLine($"Counter: {counter.Value}"); } }); } } internal class MyCounter : RealmObject { public int Value { get; set; } } }

Here are some findings:

sync-by-unito[bot] commented 3 years ago

➤ On 2020-11-20, blagoev commented:

I speculate if you remove the PropertyChanged event handler the dead lock will be gone. In Realm JS it deadlocks on a test that has notification listeners. The test is called testAddListener https://github.com/realm/realm-js/blob/master/tests/js/results-tests.js#L453

sync-by-unito[bot] commented 3 years ago

➤ On 2020-11-20, Nikola Irinchev commented:

Yes, this only happens when we have notifications in combination with multiprocess.