dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.99k stars 4.67k forks source link

Named mutex not supported on Unix #5211

Closed drieseng closed 4 years ago

drieseng commented 8 years ago

Creating a named mutex on Unix currently throws a PlatformNotSupportedException stating "Named synchronization primitives are not supported on this platform".

Is this scheduled to arrive ? I'm sure @migueldeicaza will be eager to port this from Mono to .NET Core :p

Personally, I don't think it makes sense to expose APIs on both Windows and Unix, but only implement them on one of them. In what way does the Portability Analyzer even take this into account ?

mikedn commented 8 years ago

Related to dotnet/runtime#4370

drieseng commented 8 years ago

Duplicate of issue dotnet/runtime#4370.

mikedn commented 8 years ago

I wouldn't say it's a duplicate. That issue was resolved by removing the functionality. It would be nice to actually fix the actual problem and restore the functionality.

stephentoub commented 8 years ago

I'm sure @migueldeicaza will be eager to port this from Mono to .NET Core :p

Miguel can correct me if I'm wrong, but I don't believe Mono implements this either, or more specifically I believe they implement it the same general manner that the coreclr did before it was disabled to throw those exceptions: the names are only process-wide, not cross-process. That's why we decided to throw exceptions on coreclr; otherwise, since names are typically used for cross-process synchronization, you use the names thinking you're getting cross-process synchronization, but in reality you've just got a bunch of race conditions silently waiting to cause problems.

drieseng commented 8 years ago

Reopened because of @mikedn comment.

kouvel commented 8 years ago

My search for ways to add a cross-process mutex didn't yield many options. I'm currently planning on this:

Currently, we are looking for the following features:

Any other ideas?

CC @kangaroo

janvorli commented 8 years ago

cc @krytarowski for NetBSD

krytarowski commented 8 years ago

I don't have anything portable offhand, other than maybe <semaphore.h> or pthread_mutexattr_init(3).

ghost commented 8 years ago

Mono's create named semaphore implementation is situated at: https://github.com/mono/mono/blob/ef40790/mono/io-layer/semaphores.c#L193-L289.

stephentoub commented 8 years ago

Mono's create named semaphore

Mono's implementation is not cross-process.

ChangePlaces commented 7 years ago

I'm confused, what's the current state of named Mutexes in core? Will they work on windows and linux?

krytarowski commented 7 years ago

There was an implementation with POSIX robust mutexes on Linux.

ChangePlaces commented 7 years ago

so that's a yes? It'd be really nice if yes as I can get rid of the file locking hacks!

krytarowski commented 7 years ago

I guess so, this is why I need to implement POSIX robust mutexes on my platform (NetBSD).

ChangePlaces commented 7 years ago

I've just tried on Ubuntu 14.04 and the answer is a no

stephentoub commented 7 years ago

I've just tried on Ubuntu 14.04 and the answer is a no

What code did you try? Named mutexes should work fine on in Ubuntu.

ChangePlaces commented 7 years ago

Interesting, this is my code, other processes are not honouring the mutex and are acquiring the mutex and repeating the same work. It works in Windows as expected.

using (var m = new Mutex(false, mutexName))
{
    var hasMutex = false;
    try
    {
    if (m.WaitOne(2))
    {
        hasMutex = true;
        ProcessIterationAsync(currentOutputFileNameBase, c, _config.CountryCode).Wait();
    }
    }
    catch (AbandonedMutexException e)
    {
    continue;
    }
    catch (Exception e)
    {
        continue;
    }
    finally
    {
    if (hasMutex)
    {
        m.ReleaseMutex();
    }
    }
}
kouvel commented 7 years ago

What name did you use? By default, names have session scope and sessions are more granular on Unix (each terminal gets its own session). If you haven't already, please try adding a "Global\" prefix to the name minus the quotes.

There is build-time code to detect if the system supports POSIX robust mutexes, see https://github.com/dotnet/coreclr/blob/master/src/pal/src/configure.cmake#L997 and https://github.com/dotnet/coreclr/blob/master/src/pal/src/configure.cmake#L1020. Based on that, it would use POSIX robust mutexes or file locks, but it should work either way.

kouvel commented 7 years ago

Although unrelated, in the above code, when an AbandonedMutexException is thrown, the thread is still given ownership of the lock, so you'd have to ReleaseMutex on that path as well

ChangePlaces commented 7 years ago

I prefixed the name with "Global\"as suggested here to no avail. I am running the processes in multiple screen instances. This is with RC4 (installed with apt-get)

kouvel commented 7 years ago

Would it be possible to provide a small runnable repro? I can give it a try and see what's going on.

ChangePlaces commented 7 years ago

I took this down to the most basic example I could make and it worked... so I worked backwards and fixed. It was the missing "Global\" along with a few other things - User error - thanks and sorry!

kouvel commented 7 years ago

Ok great

nvoronchev commented 5 years ago

Hi!

I have try the following program in Debian 9 and it seems mutex is not global (cross-process):

using System;
using System.Threading;

namespace test_mutex
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Started! Try to Mutex.ctor...");
            var m = new Mutex(false, @"Global\aaaaa");

            Console.WriteLine("We have the Mutex! Try to lock mutex...");
            m.WaitOne();

            Console.WriteLine("Locked! Sleep...");
            for (int i = 5; i > 0; --i)
            {
                Console.WriteLine("  {0}", i);
                Thread.Sleep(1000);
            }

            Console.WriteLine("Sleep done! Release mutex...");
            m.ReleaseMutex();

            Console.WriteLine("Done.");
            m.Close();
        }
    }
}

I started two instances of the application and both of them counting down simultaneously.

Would you be so kind to clarify is it my mistake or Mono bug?

stephentoub commented 5 years ago

Would you be so kind to clarify is it my mistake or Mono bug?

Are you using .NET Core or Mono?

nvoronchev commented 5 years ago

@stephentoub, I try Mono 5.18.0.240 and 6.1.0 (master/72512cfbcbc Thu Feb 21 19:00:53 MSK 2019).

stephentoub commented 5 years ago

Thanks. This issue / repo are for coreclr. Can you open an issue instead in http://github.com/mono/mono?

nvoronchev commented 5 years ago

@stephentoub, Oh, I see. I chose wrong project. My apologies!

stephentoub commented 5 years ago

No worries; it's confusing :)

ritchxu commented 4 years ago

Sorry for pinging on old thread. What is the situation for Semaphore? Which seems to still only support named instance on Windows.

stephentoub commented 4 years ago

Which seems to still only support named instance on Windows.

Correct.

josegomez commented 4 years ago

Would you be so kind to clarify is it my mistake or Mono bug?

Are you using .NET Core or Mono?

@stephentoub is there documentation about how global mutex works on each platform supported by net core? I’m trying to get a better understanding of the implementation for Linux, OS X and Win any pointers in the right direction would be appreciated (netcore 3.1)

stephentoub commented 4 years ago

is there documentation about how global mutex works on each platform supported by net core? I’m trying to get a better understanding of the implementation for Linux, OS X and Win any pointers in the right direction would be appreciated (netcore 3.1)

Documentation about the implementation? I don't know if @kouvel published a design doc anywhere for the Unix implementations; he might be able to point you to something. Your best bet though is probably just the implementation source code.

josegomez commented 4 years ago

Your best bet though is probably just the implementation source code.

Any way you can point me to it? The code base is extensive and so far I've had no luck with it.

kouvel commented 4 years ago

The closest summary is probably from the original PR: https://github.com/dotnet/coreclr/pull/5030. I thought they were in the code somewhere but apparently not, I have filed an issue to get those into code.

Most of the relevant code is here:

Roughly, they should behave the same way as on Windows. There may be some corner cases where they behave slightly differently, for example when the last handle to a mutex object is closed while the lock is held by a different thread.

kouvel commented 4 years ago

On Windows the native objects are used (CreateMutex, etc.), on Linuxes where pthread robust mutexes are supported, they are used, and on OSX file locks are used.