mbdavid / LiteDB

LiteDB - A .NET NoSQL Document Store in a single data file
http://www.litedb.org
MIT License
8.36k stars 1.22k forks source link

[BUG] Access to the path 'Global\xxxx.Mutex' is denied #2439

Open DanTwomey opened 4 months ago

DanTwomey commented 4 months ago

Version Which LiteDB version/OS/.NET framework version are you using. (REQUIRED) LiteDB 5.0.19 (was previously on 5.0.17 and updated to .19 to see if this issue persisted). .NET 7.0.

Describe the bug Unable to access database via 2 different .NET applications. One application is a .NET MAUI/Blazor application running .NET 7.0. Second application is a .NET 7.0 Worker Service running as a Windows Service.

Expected behavior Both applications access LiteDB without any issues.

Screenshots/Stacktrace System.UnauthorizedAccessException: 'Access to the path 'Global\E1AA37A6E09B3AA16E62C8E7D9E4F3EA1E461A3B.Mutex' is denied.'

Additional context Both applications can happily access the LiteDB when the worker service application is being run via debug in Visual Studio, however once the service is published and installed as a WIndows Service this Mutex issue comes into play and the Blazor app will throw the exception about access to the Global Mutex being denied. (LiteDB Studio also does this).

DanTwomey commented 4 months ago

We have managed to get our 2 applications working now with not too big of a change, .NET needs handling similarly to .NET Framework to avoid access being denied to the Global mutex

..\LiteDB\Client\Shared\SharedEngine.cs

#if NETFRAMEWORK
using System.Security.AccessControl;
using System.Security.Principal;
#endif
#if NETSTANDARD2_0_OR_GREATER
using System.Security.AccessControl;
using System.Security.Principal;
#endif

            try
            {
#if NETFRAMEWORK
                var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                           MutexRights.FullControl, AccessControlType.Allow);

                var securitySettings = new MutexSecurity();
                securitySettings.AddAccessRule(allowEveryoneRule);

                _mutex = new Mutex(false, "Global\\" + name + ".Mutex", out _, securitySettings);
#elif NETSTANDARD2_0_OR_GREATER

                var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                           MutexRights.FullControl, AccessControlType.Allow);

                var securitySettings = new MutexSecurity();
                securitySettings.AddAccessRule(allowEveryoneRule);

                _mutex = MutexAcl.Create(false, "Global\\" + name + ".Mutex", out _, securitySettings);
#else
                _mutex = new Mutex(false, "Global\\" + name + ".Mutex");
#endif
            }
            catch (NotSupportedException ex)
            {
                throw new PlatformNotSupportedException("Shared mode is not supported in platforms that do not implement named mutex.", ex);
            }
        }