https://bugzilla.novell.com/show_bug.cgi?id=664829
https://bugzilla.novell.com/show_bug.cgi?id=664829#c0 Summary: Data binding events not unhooked correctly, causing a memory leak in some situations Classification: Mono Product: Mono: Class Libraries Version: 2.6.x Platform: x86 OS/Version: Windows 7 Status: NEW Severity: Normal Priority: P5 - None Component: Windows.Forms AssignedTo: [email protected] ReportedBy: [email protected] QAContact: [email protected] Found By: --- Blocker: --- User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.1.249.1036 Safari/532.5 Control and data source events are not unhooked correctly, causing a memory leak in some circumstances. Reproducible: Always Steps to Reproduce: [Test] public void Test_DataBindingEventsUnhookedCorrectly() { TestDataSource dataSource = new TestDataSource(); Control.DataBindings.Add("ControlValue", dataSource, "IntProperty"); Form.Controls.Add(Control); Form.Show(); Application.DoEvents(); AssertEquals(true, Control.ControlValueChanged_IsHooked); AssertEquals(true, dataSource.IntPropertyChanged_IsHooked); Form.Dispose(); AssertEquals(false, Control.ControlValueChanged_IsHooked); AssertEquals(false, dataSource.IntPropertyChanged_IsHooked); } Form form; Form Form { get { return form ?? (form = new Form()); } } TestControl control; TestControl Control { get { return control ?? (control = new TestControl()); } } class TestControl : Control { public bool ControlValueChanged_IsHooked { get { return ControlValueChanged != null; } } public event EventHandler ControlValueChanged; public int ControlValue { get { int result; int.TryParse(Text, out result); return result; } set { Text = value.ToString(); if (ControlValueChanged != null) { ControlValueChanged(this, EventArgs.Empty); } } } } class TestDataSource { public bool IntPropertyChanged_IsHooked { get { return IntPropertyChanged != null; } } public event EventHandler IntPropertyChanged; public const int IntPropertyDefaultValue = 5; int intProperty = IntPropertyDefaultValue; public int IntProperty { get { return intProperty; } set { intProperty = value; if (IntPropertyChanged != null) { IntPropertyChanged(this, EventArgs.Empty); } } } } Actual Results: Unit test fails Expected Results: Unit test should pass, as it does with ms.net. Code added to Binding.SetControl: #if NET_2_0 internal void SetControl (IBindableComponent control) #else internal void SetControl (Control control) #endif { // ----- code added here ----- // if (control == null) // when removing the binding { // unhook control events if (this.control != null) { this.control.Validating -= new CancelEventHandler(ControlValidatingHandler); this.control.HandleCreated -= new EventHandler(ControlCreatedHandler); } // unhook the control ValueChanged event PropertyDescriptor prop_changed_event2 = GetPropertyChangedEvent(this.control, property_name); if (prop_changed_event2 != null) prop_changed_event2.RemoveValueChanged(this.control, new EventHandler(ControlPropertyChangedHandler)); // unhook the data source events if (manager is PropertyManager) { PropertyDescriptor prop_changed_event3 = GetPropertyChangedEvent(manager.Current, binding_member_info.BindingField); if (prop_changed_event3 != null) prop_changed_event3.RemoveValueChanged(manager.Current, new EventHandler(SourcePropertyChangedHandler)); } return; } // ----- code added here ----- // if (control == this.control) return; Code added to ControlBindingsCollection constructor: public ControlBindingsCollection (IBindableComponent control) { bindable_component = control; // ----- code added here ----- // // clean up the bindings once the control is disposed EventDescriptor disposed = TypeDescriptor.GetEvents(control)["Disposed"]; disposed.AddEventHandler(control, new EventHandler(delegate { foreach (Binding binding in this) { binding.SetControl(null); } })); // ----- code added here ----- // this.control = control as Control; default_datasource_update_mode = DataSourceUpdateMode.OnValidation; } Code added to ControlBindingsCollection.RemoveCore: protected override void RemoveCore (Binding dataBinding) { if (dataBinding == null) throw new ArgumentNullException ("dataBinding"); dataBinding.SetControl(null); // line added base.RemoveCore (dataBinding); } -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are the QA contact for the bug. You are the assignee for the bug. _______________________________________________ mono-bugs maillist - [email protected] http://lists.ximian.com/mailman/listinfo/mono-bugs
