[Mono-bugs] [Bug 61511][Nor] New - WaitHandle.WaitAny does not behave correctly with AutoResetEvents

bugzilla-daemon@bugzilla.ximian.com bugzilla-daemon@bugzilla.ximian.com
Tue, 13 Jul 2004 22:40:39 -0400 (EDT)


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by sebastien.robitaille@croesus.com.

http://bugzilla.ximian.com/show_bug.cgi?id=61511

--- shadow/61511	2004-07-13 22:40:39.000000000 -0400
+++ shadow/61511.tmp.24020	2004-07-13 22:40:39.000000000 -0400
@@ -0,0 +1,134 @@
+Bug#: 61511
+Product: Mono: Class Libraries
+Version: unspecified
+OS: Red Hat 9.0
+OS Details: 
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Normal
+Component: CORLIB
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: sebastien.robitaille@croesus.com               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: WaitHandle.WaitAny does not behave correctly with AutoResetEvents
+
+Description of Problem:
+When using WaitHandle.WaitAny with an array of AutoResetEvent, sometimes 
+many events are reset by a single call to WaitHandle.WaitAny when only 
+one should (For exemple, if 3 events get signaled at the same time, they 
+will all become non-signaled if a single WaitAny is waiting on them)
+
+Steps to reproduce the problem:
+1. Execute the test code at the end of this report.
+
+Actual Results:
+Test program is hanging...
+
+Expected Results:
+TEST DONE - SUCCESS!
+
+How often does this happen? 
+Very often (but not always, since it is probably a race condition)
+
+Additional Information:
+RedHat9
+Mono-1.0
+
+
+TEST CASE:
+
+using System;
+using System.Threading;
+using System.Collections;
+
+namespace MonoThreadingTest
+{
+	public class WorkerThread
+	{
+		private AutoResetEvent autoEvent = new AutoResetEvent
+(false);
+		private Thread thread = null;
+		private int timeout = 0;
+		private int index = -1;
+		public WaitHandle MyEvent
+		{
+			get { return autoEvent; }
+		}
+
+		public WorkerThread(int index, int timeout)
+		{
+			this.index = index;
+			this.timeout = timeout;
+			thread = new Thread(new ThreadStart
+(ThreadCallback));
+			thread.Start();
+		}
+
+
+		private void ThreadCallback()
+		{
+			Thread.Sleep(timeout);
+			autoEvent.Set();
+		}
+
+		static void Main(string[] args)
+		{
+			int threadCount = 64;
+
+			Random rd = new Random();
+
+			WaitHandle[] handles = new WaitHandle
+[threadCount];
+			for(int nIndex = 0; nIndex < threadCount; 
+nIndex++)
+			{
+				WorkerThread wt = new WorkerThread
+(nIndex, 1000 * rd.Next(1, 5));
+				handles[nIndex] = wt.MyEvent;
+			}
+			
+			ArrayList results = new ArrayList();
+
+			for(int nIndex = 0; nIndex < threadCount; 
+nIndex++)
+			{
+				int nWaitAnyResult = WaitHandle.WaitAny
+(handles);
+				System.Console.WriteLine("WaitAny 
+Result: " + nWaitAnyResult);
+				results.Add(nWaitAnyResult);
+			}
+
+			bool bSuccess = (results.Count == threadCount);
+			if(bSuccess)
+			{
+				for(int nIndex = 0; nIndex < threadCount; 
+nIndex++)
+				{
+					if(!results.Contains(nIndex))
+					{
+						bSuccess = false;
+						break;
+					}
+				}
+			}
+
+			if(bSuccess)
+			{
+				System.Console.WriteLine("TEST DONE - 
+SUCCESS!");
+			}
+			else
+			{
+				System.Diagnostics.Debug.Assert
+(false, "TEST FAILED!");
+				System.Console.WriteLine("TEST FAILED!");
+			}
+	
+		}
+	}
+}