Even if we are interrupted we must throw the exception only after we have regained the lock. This prevents throwing an SynchronizationLockException in the finally clause of common scenarios like :
lock (obj) {
Monitor.Wait (obj);
}
The downside of this is that, if another thread doesn't give up the lock, we could fail to abort the thread. But this is what MS does.
* 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 {
bug-389886-3.cs \
monitor.cs \
monitor-resurrection.cs \
+ monitor-wait-abort.cs \
dynamic-method-resurrection.cs \
bug-666008.cs \
bug-685908.cs \
--- /dev/null
+using System;
+using System.Threading;
+
+public class Program {
+ const int num_threads = 10;
+ public static Barrier barrier = new Barrier (num_threads + 1);
+
+ public static void ThreadFunc ()
+ {
+ object lock_obj = new object ();
+ lock (lock_obj) {
+ try {
+ barrier.SignalAndWait ();
+ Monitor.Wait (lock_obj);
+ } catch (ThreadAbortException) {
+ Thread.ResetAbort ();
+ }
+ }
+ }
+
+ public static void Main (string[] args)
+ {
+ Thread[] tarray = new Thread [num_threads];
+
+ for (int i = 0; i < num_threads; i++) {
+ tarray [i] = new Thread (new ThreadStart (ThreadFunc));
+ tarray [i].Start ();
+ }
+
+ barrier.SignalAndWait ();
+
+ for (int i = 0; i < num_threads; i++)
+ tarray [i].Abort ();
+
+ for (int i = 0; i < num_threads; i++)
+ tarray [i].Join ();
+ }
+}