Merge pull request #1406 from BrzVlad/monitor-resurrect
authorMark Probst <mark.probst@gmail.com>
Mon, 17 Nov 2014 22:17:32 +0000 (14:17 -0800)
committerMark Probst <mark.probst@gmail.com>
Mon, 17 Nov 2014 22:17:32 +0000 (14:17 -0800)
Keep the monitor link to the object active also in the resurrection case

mono/metadata/monitor.c
mono/tests/Makefile.am
mono/tests/monitor-resurrection.cs [new file with mode: 0644]

index d713709991219948a556661e3b6e97a4d95ea656..734f3f2de768403e32b6fc308cfa56ac68a80f63 100644 (file)
@@ -260,7 +260,7 @@ mon_new (gsize id)
                                                        new->wait_list = g_slist_remove (new->wait_list, new->wait_list->data);
                                                }
                                        }
-                                       mono_gc_weak_link_remove (&new->data, FALSE);
+                                       mono_gc_weak_link_remove (&new->data, TRUE);
                                        new->data = monitor_freelist;
                                        monitor_freelist = new;
                                }
@@ -428,7 +428,7 @@ retry:
                mono_monitor_allocator_lock ();
                mon = mon_new (id);
                if (InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, mon, NULL) == NULL) {
-                       mono_gc_weak_link_add (&mon->data, obj, FALSE);
+                       mono_gc_weak_link_add (&mon->data, obj, TRUE);
                        mono_monitor_allocator_unlock ();
                        /* Successfully locked */
                        return 1;
@@ -443,7 +443,7 @@ retry:
                                lw.sync = mon;
                                lw.lock_word |= LOCK_WORD_FAT_HASH;
                                if (InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, lw.sync, oldlw) == oldlw) {
-                                       mono_gc_weak_link_add (&mon->data, obj, FALSE);
+                                       mono_gc_weak_link_add (&mon->data, obj, TRUE);
                                        mono_monitor_allocator_unlock ();
                                        /* Successfully locked */
                                        return 1;
index 6268cadb4f09ff780579368c362807dc95d479de..9ba625458bd97eb0837887d17ee159547f420bc6 100644 (file)
@@ -380,6 +380,7 @@ BASE_TEST_CS_SRC=           \
        bug-599469.cs   \
        bug-389886-3.cs \
        monitor.cs      \
+       monitor-resurrection.cs \
        dynamic-method-resurrection.cs  \
        bug-666008.cs   \
        bug-685908.cs   \
diff --git a/mono/tests/monitor-resurrection.cs b/mono/tests/monitor-resurrection.cs
new file mode 100644 (file)
index 0000000..7ddd59c
--- /dev/null
@@ -0,0 +1,56 @@
+using System; 
+using System.Collections; 
+using System.Threading;
+using System.Collections.Generic;
+
+public class Foo  {
+       static Foo resurrect;
+       static Foo reference;
+       static List<Foo> list = new List<Foo> ();
+
+       ~Foo() {
+               resurrect = this;
+       }
+
+       public static void CreateFoo (int level)
+       {
+               if (level == 0)
+                       Foo.reference = new Foo ();
+               else
+                       CreateFoo (level - 1);
+       }
+
+       public static int Main() {
+               /* Allocate an object down the stack so it doesn't get pinned */
+               CreateFoo (100);
+
+               /* Allocate a MonoThreadsSync for the object */
+               Monitor.Enter (reference);
+               Monitor.Exit (reference);
+               reference = null;
+
+               /* resurrect obj */
+               GC.Collect ();
+               GC.WaitForPendingFinalizers ();
+
+               /* Allocate MonoThreadsSyncs for another thread that are locked */
+               Thread t = new Thread (new ThreadStart (resurrect.Func));
+               t.Start ();
+               t.Join ();
+
+               /* Make sure that none of the other structures overlap with the original one */
+               Monitor.Enter (resurrect);
+               return 0;
+       }
+
+       public void Func () {
+               for (int i = 0; i < 100; i++) {
+                       Foo foo = new Foo ();
+                       /* Make sure these are not collected */
+                       list.Add (foo);
+
+                       Monitor.Enter (foo);
+               }
+       }
+} 
+