diff options
author | Ludovic Henry <luhenry@microsoft.com> | 2017-09-26 06:05:58 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2017-09-29 12:21:47 +0300 |
commit | 0dd35e9d6474922034489b23e6604c46605e119a (patch) | |
tree | 6ffe2703e53de487cf3fda666bd252287fa6d784 | |
parent | 7ba4e9e7b16b1855a072093fad2db0abf96bf16a (diff) |
[w32handle] Only own first handle if doing WaitHandle.WaitAny (#5625)mono-5.4.0.203
This is the behaviour on .NET, even if it goes against the documentation at https://msdn.microsoft.com/en-us/library/tdykks7z(v=vs.110).aspx#Anchor_2
Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=59281
-rw-r--r-- | mono/metadata/w32handle.c | 9 | ||||
-rwxr-xr-x | mono/tests/Makefile.am | 3 | ||||
-rw-r--r-- | mono/tests/bug-59281.cs | 51 |
3 files changed, 60 insertions, 3 deletions
diff --git a/mono/metadata/w32handle.c b/mono/metadata/w32handle.c index 3e53ad4f880..159c6a3672e 100644 --- a/mono/metadata/w32handle.c +++ b/mono/metadata/w32handle.c @@ -1297,8 +1297,13 @@ mono_w32handle_wait_multiple (gpointer *handles, gsize nhandles, gboolean waital signalled = (waitall && count == nhandles) || (!waitall && count > 0); if (signalled) { - for (i = 0; i < nhandles; i++) - own_if_signalled (handles [i], &abandoned [i]); + for (i = 0; i < nhandles; i++) { + if (own_if_signalled (handles [i], &abandoned [i]) && !waitall) { + /* if we are calling WaitHandle.WaitAny, .NET only owns the first one; it matters for Mutex which + * throw AbandonedMutexException in case we owned it but didn't release it */ + break; + } + } } mono_w32handle_unlock_handles (handles, nhandles); diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index a4bdf542740..47fa1563435 100755 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -515,7 +515,8 @@ TESTS_CS_SRC= \ runtime-invoke.gen.cs \ imt_big_iface_test.cs \ bug-58782-plain-throw.cs \ - bug-58782-capture-and-throw.cs + bug-58782-capture-and-throw.cs \ + bug-59281.cs if AMD64 TESTS_CS_SRC += async-exc-compilation.cs finally_guard.cs finally_block_ending_in_dead_bb.cs diff --git a/mono/tests/bug-59281.cs b/mono/tests/bug-59281.cs new file mode 100644 index 00000000000..94250c277a7 --- /dev/null +++ b/mono/tests/bug-59281.cs @@ -0,0 +1,51 @@ +using System; +using System.Threading; + +class Driver +{ + + static readonly Mutex[] mutexes = new Mutex[2]; + + public static void Main(string[] args) + { + for (int i = 0; i < mutexes.Length; i++) { + mutexes [i] = new Mutex(); + } + + Thread thread1 = new Thread(() => { + for (int i = 0; i < 1; i++) { + int idx = -1; + try { + idx = WaitHandle.WaitAny (mutexes); + Console.WriteLine($"Thread 1 iter: {i} with mutex: {idx}"); + } finally { + if (idx != -1) + mutexes [idx].ReleaseMutex(); + } + } + + Console.WriteLine("Thread 1 ended"); + }); + + thread1.Start(); + thread1.Join(); + + Thread thread2 = new Thread(() => { + for (int i = 0; i < 1000; i++) { + int idx = -1; + try { + idx = WaitHandle.WaitAny (mutexes); + Console.WriteLine($"Thread 2 iter: {i} with mutex: {idx}"); + } finally { + if (idx != -1) + mutexes [idx].ReleaseMutex(); + } + } + + Console.WriteLine("Thread 2 ended"); + }); + + thread2.Start(); + thread2.Join(); + } +}
\ No newline at end of file |