Bug 539138 - InvalidOperationException when trying to launch columnheader.py sample
Summary: InvalidOperationException when trying to launch columnheader.py sample
Status: NEW
Alias: None
Product: UI Automation
Classification: Mono
Component: Winforms - UIA (show other bugs)
Version: Unspecified
Hardware: Other Other
: P5 - None : Normal
Target Milestone: ---
Assignee: E-mail List
QA Contact: E-mail List
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-09-14 21:55 UTC by Andres Aragoneses
Modified: 2009-09-15 20:13 UTC (History)
0 users

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andres Aragoneses 2009-09-14 21:55:01 UTC
[Debug 17:49:18.492] AutomationBridge: Creating new UiaAtkBridge.TreeItem adapter for Mono.UIAutomation.Winforms.ListViewProvider+ListViewListItemEditProvider
Exception in Gtk# callback delegate
  Note: Applications can use GLib.ExceptionManager.UnhandledException to handle the exception.
System.InvalidOperationException: Collection was modified;enumeration operation may not execute.
  at System.Collections.Generic.List`1+Enumerator[Mono.UIAutomation.Winforms.FragmentControlProvider].MoveNext () [0x00000] 
  at Mono.UIAutomation.Winforms.FragmentControlProvider+<GetEnumerator>c__Iterator0.MoveNext () [0x00078] in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/uia2atkMAKE/UIAutomationWinforms/UIAutomationWinforms/Mono.UIAutomation.Winforms/FragmentControlProvider.cs:152 
  at Mono.UIAutomation.Winforms.ListViewProvider+ListViewGroupProvider.get_ItemsBoundingRectangle () [0x00041] in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/uia2atkMAKE/UIAutomationWinforms/UIAutomationWinforms/Mono.UIAutomation.Winforms/ListViewProvider.cs:687 
  at Mono.UIAutomation.Winforms.ListViewProvider+ListViewGroupProvider.GetProviderPropertyValue (Int32 propertyId) [0x0003e] in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/uia2atkMAKE/UIAutomationWinforms/UIAutomationWinforms/Mono.UIAutomation.Winforms/ListViewProvider.cs:652 
  at Mono.UIAutomation.Winforms.SimpleControlProvider.GetPropertyValue (Int32 propertyId) [0x0004d] in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/uia2atkMAKE/UIAutomationWinforms/UIAutomationWinforms/Mono.UIAutomation.Winforms/SimpleControlProvider.cs:399 
  at UiaAtkBridge.Adapter.OnRefStateSet () [0x000bf] in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/uia2atkMAKE/UiaAtkBridge/UiaAtkBridge/Adapter.cs:219 
  at UiaAtkBridge.ComponentParentAdapter.OnRefStateSet () [0x00000] in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/uia2atkMAKE/UiaAtkBridge/UiaAtkBridge/ComponentParentAdapter.cs:144 
  at Atk.Object.RefStateSet_cb (IntPtr raw) [0x0000d] in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/gtk-sharp/atk/generated/Object.custom:128 
   at GLib.ExceptionManager.RaiseUnhandledException(System.Exception e, Boolean is_terminal) in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/gtk-sharp/glib/ExceptionManager.cs:line 58
   at Atk.Object.RefStateSet_cb(IntPtr raw) in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/gtk-sharp/atk/generated/Object.custom:line 133
   at GLib.MainLoop.g_main_loop_run(IntPtr )
   at GLib.MainLoop.Run() in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/gtk-sharp/glib/MainLoop.cs:line 59
   at UiaAtkBridge.Monitor.GLibMainLoopThread() in /home/knocte/Documents/iDocs/Proyectos/mono/a11y/uia2atkMAKE/UiaAtkBridge/UiaAtkBridge/Monitor.cs:line 145
Comment 1 Andres Aragoneses 2009-09-15 20:13:20 UTC
Threading bug (not deterministic).

Published this patch in RB ( http://reviews.mono-a11y.org/r/450/diff/ ):

Index: UIAutomationWinforms/UIAutomationWinforms/Mono.UIAutomation.Winforms/FragmentControlProvider.cs
===================================================================
--- UIAutomationWinforms/UIAutomationWinforms/Mono.UIAutomation.Winforms/FragmentControlProvider.cs	(revision 141771)
+++ UIAutomationWinforms/UIAutomationWinforms/Mono.UIAutomation.Winforms/FragmentControlProvider.cs	(working copy)
@@ -149,7 +149,7 @@
 		
 		public IEnumerator<FragmentControlProvider> GetEnumerator ()
 		{
-			foreach (FragmentControlProvider childProvider in children)
+			foreach (FragmentControlProvider childProvider in new List<FragmentControlProvider> (children))
 				yield return childProvider;
 		}
 		


However, this led to a discussion in IRC:

(03:55:43 PM) brad: knocte: hrm... I don't really see how this fixes the threading bug
(03:55:58 PM) brad: yes, you're copying the children array, but it's still not thread safe
(03:56:17 PM) brad: and copying the children array in GetEnumerator is going to be *really* expensive
(03:56:45 PM) knocte: mmm
(03:57:53 PM) knocte: I think it fixes the threading bug (I've seen code that does this) because it allows the collection to be modified while the copy is intact
(03:58:02 PM) knocte: I'll check about the complexity though
(03:58:21 PM) brad: unless the list is synchronized, copying the data while it is being modified could corrupt the data
(03:59:05 PM) knocte: ok, then I didn't fix it completely; I fixed it for the case in which the data is being modified while inside the foreach loop, not while copying the data
(03:59:17 PM) brad: yes, perhaps
(03:59:36 PM) brad: but the right fix is to actually add locking
(03:59:59 PM) knocte: but with what? the stacktrace doesn't give much more info
(04:00:21 PM) knocte: with every member that access the collection?
(04:01:19 PM) brad: well, I don't know about that specific instance
(04:01:35 PM) brad: but modifying the children list while you're iterating it is a bad idea, if that is indeed what is happening
(04:02:14 PM) brad: (again, I haven't seen the stack trace, so I can't comment on specifics)
(04:02:30 PM) knocte: the stacktrace is on the bug referenced
(04:03:43 PM) brad: eep... yeah, the only safe way to modify a list while you're iterating it is to iterate using indicies
(04:04:22 PM) knocte: well, I would say, that may preven InvalidOperationExceptions, but would still cause IndexOutOfRangeExceptions
(04:04:37 PM) knocte: or not, mm, not sure
(04:04:49 PM) brad: if children is being modified as you're iterating it, yes
(04:05:21 PM) brad: because you can't assume that once you check if the index is less than count, that that condition will exist during the block
(04:05:38 PM) brad: thus, locking
(04:06:05 PM) brad: *but* if you're modifying the children array while iterating, that's a different case
(04:07:55 PM) knocte: ok, then as it's not trivial, let's write this on the bug and move on, this is in the end 1.0 work..
(04:09:20 PM) brad: nod

So, as this is not trivial to fix, we're postponing it.