[Mono-bugs] [Bug 75729][Nor] New - Thread lock causing problems with the X layer interface

bugzilla-daemon at bugzilla.ximian.com bugzilla-daemon at bugzilla.ximian.com
Sat Aug 6 05:11:04 EDT 2005


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 paul at all-the-johnsons.co.uk.

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

--- shadow/75729	2005-08-06 05:11:04.000000000 -0400
+++ shadow/75729.tmp.802	2005-08-06 05:11:04.000000000 -0400
@@ -0,0 +1,271 @@
+Bug#: 75729
+Product: Mono: Class Libraries
+Version: unspecified
+OS: 
+OS Details: FC4
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Normal
+Component: Windows.Forms
+AssignedTo: mono-bugs at ximian.com                            
+ReportedBy: paul at all-the-johnsons.co.uk               
+QAContact: mono-bugs at ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Thread lock causing problems with the X layer interface
+
+Please fill in this template when reporting a bug, unless you know what you
+are doing.
+Description of Problem:
+The code in the additional information will compile and run, but after 100
+or so threads, causes a stack throwback. It is probably some form of lock
+problem on the threader.
+
+I have no problems having this added as a test case :-)
+
+Steps to reproduce the problem:
+1. Compile the code and run. Use an x86 Linux box
+2. 
+3. 
+
+Actual Results:
+The following stack throwback is given
+
+Unhandled Exception: System.ObjectDisposedException: The object was
+used after being disposed.
+in [0x0002d] System.Threading.WaitHandle:CheckDisposed ()
+in [0x00001] (at mcs/class/corlib/System.Threading/WaitHandle.cs:177)
+System.Threading.WaitHandle:WaitOne ()
+in [0x0000e] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/AsyncMethodResult.cs:78)
+System.Windows.Forms.AsyncMethodResult:Complete (System.Object result)
+in [0x00062] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIDriver.cs:279)
+System.Windows.Forms.XplatUIDriverSupport:ExecuteClientMessage
+(GCHandle gchandle)
+in [0x00a8c] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs:2536)
+System.Windows.Forms.XplatUIX11:GetMessage (System.Windows.Forms.MSG
+msg, IntPtr handle, Int32 wFilterMin, Int32 wFilterMax)
+in [0x00009] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs:440)
+System.Windows.Forms.XplatUI:GetMessage (System.Windows.Forms.MSG msg,
+IntPtr hWnd, Int32 wFilterMin, Int32 wFilterMax)
+in [0x0012e] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/Application.cs:365)
+System.Windows.Forms.Application:Run ()
+in [0x0004a] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/Application.cs:388)
+System.Windows.Forms.Application:Run
+(System.Windows.Forms.ApplicationContext context)
+in [0x0000c] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/Application.cs:379)
+System.Windows.Forms.Application:Run (System.Windows.Forms.Form
+mainForm)
+in <0x000b8> Sharing1:Main (System.String[] args)
+
+Expected Results:
+The program should run
+
+How often does this happen? 
+Always
+
+Additional Information:
+
+Source listing
+
+using System;
+using System.Threading;
+using System.Windows.Forms;
+using System.Drawing;
+
+public class Sharing1 : Form
+{
+ private TextBox accessCountBox = new TextBox();
+ private Button start = new Button();
+ private Button watch = new Button();
+ private int accessCount = 0;
+
+ public void incrementAccess()
+ {
+   accessCount++;
+   UpdateAccess();
+ }
+
+ public void UpdateAccess()
+ {
+        if (!accessCountBox.InvokeRequired)
+           accessCountBox.Text = accessCount.ToString();
+        else
+           accessCountBox.BeginInvoke(new MethodInvoker(UpdateAccess));
+ }
+
+ private int numCounters = 12;
+ private int numWatchers = 15;
+ private TwoCounter[] s;
+
+ public Sharing1()
+ {
+   ClientSize = new Size(450, 480);
+   Panel p = new Panel();
+   p.Size = new Size(400, 50);
+   start.Click += new EventHandler(StartAllThreads);
+   watch.Click += new EventHandler(StartAllWatchers);
+
+   accessCountBox.Text = "0";
+   accessCountBox.Location = new Point(10, 10);
+   start.Text = "Start threads";
+   start.Location = new Point(110, 10);
+   start.Width = 80;
+   watch.Text = "Begin watching";
+   watch.Location = new Point(210, 10);
+   watch.Width = 180;
+
+   p.Controls.Add(start);
+   p.Controls.Add(watch);
+   p.Controls.Add(accessCountBox);
+
+   s = new TwoCounter[numCounters];
+   for (int i = 0; i < s.Length; i++)
+   {
+     s[i] = new TwoCounter(new TwoCounter.IncrementAccess(incrementAccess));
+     s[i].Location = new Point(10, 50 + s[i].Height * i);
+     Controls.Add(s[i]);
+   }
+
+   this.Closed += new EventHandler(StopAllThreads);
+   Controls.Add(p);
+ }
+
+ public void StartAllThreads(object sender, EventArgs ea)
+ {
+   for (int i = 0; i < s.Length; i++)
+     s[i].Start();
+ }
+
+ public void StopAllThreads(object sender, EventArgs ea)
+ {
+   for (int i = 0; i < s.Length; i++)
+     if (s[i] != null)
+       s[i].Stop();
+ }
+
+ public void StartAllWatchers(object sender, EventArgs ea)
+ {
+   for (int i = 0; i < numWatchers; i++)
+     new Watcher(s);
+ }
+
+ public static void Main(string [] args)
+ {
+   Sharing1 app = new Sharing1();
+   if (args.Length > 0)
+   {
+     app.numCounters = SByte.Parse(args[0]);
+     if (args.Length == 2)
+       app.numCounters = SByte.Parse(args[1]);
+   }
+   Application.Run(app);
+ }
+}
+
+class TwoCounter : Panel
+{
+ private bool started = false;
+ private Label t1;
+ private Label t2;
+ private Label lbl;
+ private Thread t;
+
+ private int count1 = 0, count2 = 0;
+ public delegate void IncrementAccess();
+ IncrementAccess del;
+
+ public TwoCounter(IncrementAccess del)
+ {
+   this.del = del;
+   this.Size = new Size(350, 30);
+   this.BorderStyle = BorderStyle.Fixed3D;
+   t1 = new Label();
+   t1.Location = new Point(10, 10);
+   t2 = new Label();
+   t2.Location = new Point(110, 10);
+   lbl = new Label();
+   lbl.Location = new Point(210, 10);
+   lbl.Text = "Count1 == Count2";
+   Controls.AddRange(new Control[] {t1, t2, lbl} );
+
+   t = new Thread(new ThreadStart(run));
+ }
+
+ public void Start()
+ {
+   if (!started)
+   {
+     started = true;
+     t.Start();
+   }
+ }
+
+ public void Stop()
+ {
+   t.Abort();
+ }
+
+ public void run()
+ {
+   while(true)
+   {
+         UpdateLabels();
+     Thread.Sleep(500);
+   }
+ }
+ 
+ public void synchTest()
+ {
+   del();
+   if (count1 != count2)
+        UpdateSynch();
+ }
+ 
+ private void UpdateLabels()
+ {
+        if (!t1.InvokeRequired) {
+     t1.Text = (++count1).ToString();
+     t2.Text = (++count2).ToString();   
+   } else  // Will be queued for execution in the UI Thread 
+                t1.BeginInvoke(new MethodInvoker(UpdateLabels));
+ }
+ 
+ private void UpdateSynch()
+ {
+        if (!lbl.InvokeRequired)
+     lbl.Text = "Unsynched";
+    else  // Will be queued for execution in the UI Thread 
+        lbl.BeginInvoke(new MethodInvoker(UpdateSynch));
+ }
+ 
+}
+
+class Watcher
+{
+ TwoCounter[] s;
+
+ public Watcher(TwoCounter[] s)
+ {
+   this.s = s;
+   new Thread(new ThreadStart(run)).Start();
+ }
+
+ public void run()
+ {
+   while(true)
+   {
+     for(int i = 0; i < s.Length; i++)
+       s[i].synchTest();
+     Thread.Sleep(500);
+   }
+ }
+}


More information about the mono-bugs mailing list