EDCD / EDDI

Companion application for Elite Dangerous
Other
444 stars 81 forks source link

Memory leak in EDDI's VA configuration screen #1481

Closed jwvanderbeck closed 4 years ago

jwvanderbeck commented 5 years ago

EDDI version in which issue is found

3,4,3

VoiceAttack version in which issue is found (as applicable)

1.7.7

Steps to reproduce

  1. Issue the command to open EDDI configuration ("configure eddi")
  2. Select the Speech Responder tab
  3. Open task mnanager and note memory use by VoiceAttack
  4. Close EDDI configuration window
  5. Re-Issue the command to open the window
  6. Close the window
  7. Repeat opening and closing the window and observe VoiceAttack memory usage.

Expected

Repeated opening and closing of the EDDI config screen should not increase VoiceAttack memory usage.

Observed

Each time the EDDI window is opened, more memory is allocated by VoiceAttack that is not released when the configuration screen is closed.

As a result, after a while VoiceAttack/EDDI will start erroring or crashing with an OutOfMemory exception. System is not out of memory but it mostly is a local memory allocation that VA or VA plugins are allowed to use?

Investigation

2019-09-08T19:37:20 [Warning] VoiceAttackPlugin:InvokeConfiguration Show configuration window failed System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.Windows.Controls.ItemContainerGenerator.ContainerFromItem(Object item)
   at System.Windows.Controls.DataGrid.TryFindCell(Object item, DataGridColumn column)
   at System.Windows.Automation.Peers.DataGridCellItemAutomationPeer.get_OwningCell()
   at System.Windows.Automation.Peers.DataGridCellItemAutomationPeer.get_OwningCellPeer()
   at System.Windows.Automation.Peers.DataGridItemAutomationPeer.GetOrCreateCellItemPeer(DataGridColumn column, Boolean addParentInfo)
   at System.Windows.Automation.Peers.DataGridItemAutomationPeer.GetCellItemPeers()
   at System.Windows.Automation.Peers.DataGridRowAutomationPeer.GetChildrenCore()
   at System.Windows.Automation.Peers.AutomationPeer.EnsureChildren()
   at System.Windows.Automation.Peers.DataGridItemAutomationPeer.GetChildrenCore()
   at System.Windows.Automation.Peers.AutomationPeer.EnsureChildren()
   at System.Windows.Automation.Peers.AutomationPeer.GetChildren()
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.isDescendantOf(AutomationPeer parent)
   at System.Windows.Automation.Peers.AutomationPeer.ValidateConnected(AutomationPeer connectedPeer)
   at MS.Internal.Automation.ElementProxy.StaticWrap(AutomationPeer peer, AutomationPeer referencePeer)
   at System.Windows.Automation.Peers.AutomationPeer.ProviderFromPeer(AutomationPeer peer)
   at System.Windows.Automation.Peers.AutomationPeer.RaiseAutomationEvent(AutomationEvents eventId)
   at System.Windows.Automation.Peers.SelectorAutomationPeer.RaiseSelectionEvents(SelectionChangedEventArgs e)
   at System.Windows.Controls.ComboBox.OnSelectionChanged(SelectionChangedEventArgs e)
   at System.Windows.Controls.Primitives.Selector.InvokeSelectionChanged(List`1 unselectedInfos, List`1 selectedInfos)
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
   at System.Windows.Controls.Primitives.Selector.SelectionChanger.SelectJustThisItem(ItemInfo info, Boolean assumeInItemsCollection)
   at System.Windows.Controls.Primitives.Selector.SelectItemWithValue(Object value, Boolean selectNow)
   at System.Windows.Controls.Primitives.Selector.CoerceSelectedValue(DependencyObject d, Object value)
   at System.Windows.DependencyObject.ProcessCoerceValue(DependencyProperty dp, PropertyMetadata metadata, EntryIndex& entryIndex, Int32& targetIndex, EffectiveValueEntry& newEntry, EffectiveValueEntry& oldEntry, Object& oldValue, Object baseValue, Object controlValue, CoerceValueCallback coerceValueCallback, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, Boolean skipBaseValueChecks)
   at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
   at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
   at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
   at System.Windows.Data.BindingExpression.Activate(Object item)
   at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
   at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
   at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
   at MS.Internal.Data.DataBindEngine.Run(Object arg)
   at MS.Internal.Data.DataBindEngine.OnLayoutUpdated(Object sender, EventArgs e)
   at System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
   at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Window.ShowHelper(Object booleanBox)
   at System.Windows.Window.Show()
   at System.Windows.Window.ShowDialog()
   at EddiVoiceAttackResponder.VoiceAttackPlugin.<>c.<InvokeConfiguration>b__19_0()
2019-09-08T19:40:32 [Warning] ScriptResolver:resolveScript Failed to resolve the: Bodies to map script. System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Cottle.Values.ReflectionValue.MemberReader.<>c__DisplayClass6_0.<.ctor>b__0(Object s)
   at Cottle.Values.ReflectionValue.MemberReader.Extract(Object source)
   at Cottle.Values.ReflectionValue.Resolve()
   at Cottle.Values.ResolveValue.Acquire()
   at Cottle.Values.ResolveValue.get_Fields()
   at Cottle.Documents.Simple.Evaluators.AccessEvaluator.Evaluate(IStore store, TextWriter output)
   at Cottle.Documents.Simple.Nodes.IfNode.Render(IStore store, TextWriter output, Value& result)
   at Cottle.Documents.Simple.Nodes.CompositeNode.Render(IStore store, TextWriter output, Value& result)
   at Cottle.Documents.Simple.Nodes.ForNode.Render(IStore store, TextWriter output, Value& result)
   at Cottle.Documents.Simple.Nodes.CompositeNode.Render(IStore store, TextWriter output, Value& result)
   at Cottle.Documents.SimpleDocument.Render(IStore store, TextWriter writer)
   at Cottle.Documents.AbstractDocument.Render(IStore store)
   at EddiSpeechResponder.ScriptResolver.resolveScript(String script, BuiltinStore store, Boolean master, Script scriptObject) 
Tkael commented 5 years ago

This warrants some thinking about but I'm seeing an increase in memory utilization by about 50,000 KB every time that EDDI's UI is invoked in VoiceAttack.

Tkael commented 5 years ago

Possible cause: Event handlers not fully detached prior to closing the window so resources remain in memory and are not released when the window closes. https://social.msdn.microsoft.com/Forums/vstudio/en-US/b2861707-81d6-45d9-853a-11bb9989137a/memory-leak-close-doesnt-dispose-window?forum=wpf