Skip to content
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

Support in-process named mutexes in managed implementation #55199

Merged
merged 1 commit into from
Jul 8, 2021
Merged

Support in-process named mutexes in managed implementation #55199

merged 1 commit into from
Jul 8, 2021

Conversation

uweigand
Copy link
Contributor

@uweigand uweigand commented Jul 6, 2021

This follows the suggestion in #48720 (comment)

Note that the current managed Mutex implementation considers a mutex abandoned not only if the thread holding it terminates, but also when the SafeEventHandle refering to it is closed. This is clearly not correct for named mutexes, which can have multiple handles refering to it. In this patch, I've chosen to consider a named mutex abandoned once all handles to it are closed -- an alternate approach would be to just not have that special case at all and only abandon the mutex on thread exit (because as long as the mutex is held, it would in principle be possible to re-open another handle to it by name). Let me know if that alternate approach would be preferable.

@ghost
Copy link

ghost commented Jul 6, 2021

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

Issue Details

This follows the suggestion in #48720 (comment)

Note that the current managed Mutex implementation considers a mutex abandoned not only if the thread holding it terminates, but also when the SafeEventHandle refering to it is closed. This is clearly not correct for named mutexes, which can have multiple handles refering to it. In this patch, I've chosen to consider a named mutex abandoned once all handles to it are closed -- an alternate approach would be to just not have that special case at all and only abandon the mutex on thread exit (because as long as the mutex is held, it would in principle be possible to re-open another handle to it by name). Let me know if that alternate approach would be preferable.

Author: uweigand
Assignees: -
Labels:

area-System.Threading

Milestone: -

@uweigand
Copy link
Contributor Author

uweigand commented Jul 6, 2021

I see some of the runs show failures in System.Threading.Tests.MutexTests.AbandonExisting, this is most likely this problem: #55198 which should be merged first (or if you prefer merged into this PR).

@jkotas
Copy link
Member

jkotas commented Jul 6, 2021

we now see failures due to use of named Mutexes in parts of the .NET SDK itself.

Is the SDK going to work reliably with this partial implementation?

@uweigand
Copy link
Contributor Author

uweigand commented Jul 6, 2021

we now see failures due to use of named Mutexes in parts of the .NET SDK itself.

Is the SDK going to work reliably with this partial implementation?

This is a good question, and I do not know a definite answer to that. What I can say is:

  • I haven't seen any issues working with a native s390x SDK built using this patch; it builds e.g. runtime, roslyn and aspnetcore and can run the test suites (runtime 100% pass, roslyn and aspnetcore still have a few failures but nothing that seems related to problems in the host SDK). This is all on a machine with 8 CPUs.
  • The behavior with this patch matches the original behavior of the Mono-based mutexes in .NET 5 (and early .NET 6). I haven't seen any SDK issues there either.
  • Without this patch the SDK is basically unusable due to unhandled exceptions. E.g. just a plain "dotnet new" will abort.

I guess a full solution would be preferable, but that seems a much larger effort, and I'm not even sure how to do that in a pure managed implementation. Unless we want to link the Mono runtime also against the PAL layer?

@jkotas
Copy link
Member

jkotas commented Jul 6, 2021

The behavior with this patch matches the original behavior of the Mono-based mutexes in .NET 5 (and early .NET 6).

Ok. So this makes it as broken as it always was.

Unless we want to link the Mono runtime also against the PAL layer?

I do not see why it would be needed. src/libraries/native PAL layer can be extended as necessary, without coupling it with the Mono runtime.

@jkotas jkotas closed this Jul 7, 2021
@jkotas jkotas reopened this Jul 7, 2021
@jkotas
Copy link
Member

jkotas commented Jul 7, 2021

/azp run runtime

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@lambdageek
Copy link
Member

I do not see why it would be needed. src/libraries/native PAL layer can be extended as necessary, without coupling it with the Mono runtime.

@jkotas Do you know if src/coreclr/pal/src/include/pal/mutex.{h,c}pp depend on anything from CoreCLR? Would there be any complications in moving it to the libraries PAL layer (and porting to C)?

@jkotas
Copy link
Member

jkotas commented Jul 7, 2021

Do you know if src/coreclr/pal/src/include/pal/mutex.{h,c}pp depend on anything from CoreCLR?

It is coupled with the rest of the CoreCLR PAL. I do not think we would want to move it over wholesale, instead cherry pick just the pieces relevant for the shared mutex implementation. It should not be much.

@lambdageek
Copy link
Member

I think a managed in-proc implementation is still useful - it's a better fit for WASM and iOS+Android. We don't get a lot of freedom to launch new processes on mobile, and in any case relying on shared FS access is probably the wrong thing.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM otherwise. Thanks!

@@ -24,7 +29,9 @@ private void CreateMutexCore(bool initiallyOwned, string? name, out bool created

private static OpenExistingResult OpenExistingWorker(string name, out Mutex? result)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
OpenExistingResult status = WaitSubsystem.OpenNamedMutex(name, out var safeWaitHandle);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OpenExistingResult status = WaitSubsystem.OpenNamedMutex(name, out var safeWaitHandle);
OpenExistingResult status = WaitSubsystem.OpenNamedMutex(name, out SafeWaitHandle? safeWaitHandle);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed those. Now fixed.

/// Dictionary to look up named waitable objects. This implementation only supports in-process
/// named waitable objects. Currently only named mutexes are supported.
/// </summary>
private static readonly Dictionary<string, WaitableObject> s_namedObjects = new Dictionary<string, WaitableObject>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create it on demand in the one place that does Add so that the Dictionary won't be created in apps that do not used named mutexes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this?

* Partially addresses #48720

* Use a dictionary to perform the name to object lookup

* Allow multiple handles to refer to a single waitable object

* Abandon mutex only when all handles refering to it are closed

* Re-enable test cases disabled due to the above issue
@lambdageek lambdageek merged commit 7ab7eaa into dotnet:main Jul 8, 2021
@uweigand uweigand deleted the mono-namedmutex branch July 14, 2021 12:20
@ghost ghost locked as resolved and limited conversation to collaborators Aug 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants