Merge pull request #2799 from BrzVlad/fix-conc-card-clean
[mono.git] / mono / metadata / monitor.c
index b05a8416aac761b86579a210988f5627e168bc6d..b068745dff68636300170c8abe8a48aa487fbc71 100644 (file)
@@ -392,7 +392,7 @@ mon_new (gsize id)
                                        if (new_->wait_list) {
                                                /* Orphaned events left by aborted threads */
                                                while (new_->wait_list) {
-                                                       LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d): Closing orphaned event %d", mono_thread_info_get_small_id (), new->wait_list->data));
+                                                       LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d): Closing orphaned event %d", mono_thread_info_get_small_id (), new_->wait_list->data));
                                                        CloseHandle (new_->wait_list->data);
                                                        new_->wait_list = g_slist_remove (new_->wait_list, new_->wait_list->data);
                                                }
@@ -896,7 +896,7 @@ retry_contended:
                 * We have to obey a stop/suspend request even if 
                 * allow_interruption is FALSE to avoid hangs at shutdown.
                 */
-               if (!mono_thread_test_state (mono_thread_internal_current (), (MonoThreadState)(ThreadState_StopRequested | ThreadState_SuspendRequested))) {
+               if (!mono_thread_test_state (mono_thread_internal_current (), (MonoThreadState)(ThreadState_StopRequested | ThreadState_SuspendRequested | ThreadState_AbortRequested))) {
                        if (ms != INFINITE) {
                                now = mono_msec_ticks ();
                                if (now < then) {
@@ -1082,8 +1082,13 @@ ves_icall_System_Threading_Monitor_Monitor_try_enter (MonoObject *obj, guint32 m
 
        do {
                res = mono_monitor_try_enter_internal (obj, ms, TRUE);
-               if (res == -1)
-                       mono_thread_interruption_checkpoint ();
+               if (res == -1) {
+                       MonoException *exc = mono_thread_interruption_checkpoint ();
+                       if (exc) {
+                               mono_set_pending_exception (exc);
+                               return FALSE;
+                       }
+               }
        } while (res == -1);
        
        return res == 1;
@@ -1096,8 +1101,13 @@ ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObject
        do {
                res = mono_monitor_try_enter_internal (obj, ms, TRUE);
                /*This means we got interrupted during the wait and didn't got the monitor.*/
-               if (res == -1)
-                       mono_thread_interruption_checkpoint ();
+               if (res == -1) {
+                       MonoException *exc = mono_thread_interruption_checkpoint ();
+                       if (exc) {
+                               mono_set_pending_exception (exc);
+                               return;
+                       }
+               }
        } while (res == -1);
        /*It's safe to do it from here since interruption would happen only on the wrapper.*/
        *lockTaken = res == 1;
@@ -1298,34 +1308,14 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms)
         * about the monitor error checking
         */
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
-       
-       if (mono_thread_interruption_requested ()) {
-               /* 
-                * Can't remove the event from wait_list, since the monitor is not locked by
-                * us. So leave it there, mon_new () will delete it when the mon structure
-                * is placed on the free list.
-                * FIXME: The caller expects to hold the lock after the wait returns, but it
-                * doesn't happen in this case:
-                * http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97268
-                */
-               return FALSE;
-       }
 
        /* Regain the lock with the previous nest count */
        do {
                regain = mono_monitor_try_enter_inflated (obj, INFINITE, TRUE, id);
-               if (regain == -1) 
-                       mono_thread_interruption_checkpoint ();
+               /* We must regain the lock before handling interruption requests */
        } while (regain == -1);
 
-       if (regain == 0) {
-               /* Something went wrong, so throw a
-                * SynchronizationLockException
-                */
-               CloseHandle (event);
-               mono_set_pending_exception (mono_get_exception_synchronization_lock ("Failed to regain lock"));
-               return FALSE;
-       }
+       g_assert (regain == 1);
 
        mon->nest = nest;