2
votes

After running my application (.Net 4.5, 64-bit, WPF) a long time (one to two weeks) I encounter the following app crash:

Faulting application name: XY.exe, Version: 2.12.2.2, Time: 0x5bade142
Faulting module name: KERNELBASE.dll, Version: 6.1.7601.24150, Time: 0x5b0cbc65
Exception code: 0xe0434352
Fault offset: 0x000000000001a06d
Faulting process id: 0x8694
Faulting application start time: 0x01d457228a130410
Faulting application path: C:\Testsysteme\YY.exe
Faulting module path: C:\Windows\system32\KERNELBASE.dll
Report Id: dbfc630b-c61f-11e8-bc27-1866da0d15ef

Application: XY.exe
Frameworkversion: v4.0.30319
Description: The process was terminated due to an unhandled exception
Exception information: System.ComponentModel.Win32Exception
at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D)
at MS.Win32.HwndWrapper..ctor(Int32, Int32, Int32, Int32, Int32, Int32, Int32, System.String, IntPtr, MS.Win32.HwndWrapperHook[])
at System.Windows.Interop.HwndSource.Initialize(System.Windows.Interop.HwndSourceParameters)
at System.Windows.Interop.HwndSource..ctor(System.Windows.Interop.HwndSourceParameters)
at System.Windows.Controls.Primitives.Popup+PopupSecurityHelper.BuildWindow(Int32, Int32, System.Windows.Media.Visual, Boolean, System.Windows.Interop.HwndSourceHook, System.Windows.AutoResizedEventHandler)
at System.Windows.Controls.Primitives.Popup.BuildWindow(System.Windows.Media.Visual)
at System.Windows.Controls.Primitives.Popup.CreateWindow(Boolean)
at System.Windows.Controls.Primitives.Popup.OnIsOpenChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, System.Windows.EffectiveValueEntry ByRef, Boolean, Boolean, System.Windows.OperationType)
at System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty, System.Object, System.Windows.PropertyMetadata, Boolean, Boolean, System.Windows.OperationType, Boolean)
at System.Windows.Data.BindingOperations.SetBinding(System.Windows.DependencyObject, System.Windows.DependencyProperty, System.Windows.Data.BindingBase)
at System.Windows.Controls.Primitives.Popup.CreateRootPopup(System.Windows.Controls.Primitives.Popup, System.Windows.UIElement)
at System.Windows.Controls.ToolTip.OnIsOpenChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs)
at System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, System.Windows.EffectiveValueEntry ByRef, Boolean, Boolean, System.Windows.OperationType)
at System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty, System.Object, System.Windows.PropertyMetadata, Boolean, Boolean, System.Windows.OperationType, Boolean)
at System.Windows.DependencyObject.SetValue(System.Windows.DependencyProperty, System.Object)
at System.Windows.Controls.PopupControlService.RaiseToolTipOpeningEvent()
at System.Windows.Threading.DispatcherTimer.FireTick(System.Object)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
at MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
at System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
at System.Windows.Application.RunDispatcher(System.Object)
at System.Windows.Application.RunInternal(System.Windows.Window)
at XY.App.Main()

Logging of the unhandled exception additionally showed:

System.ComponentModel.Win32Exception (0x80004005): Not enough storage is available to process this command

I already found a link with a basic description of the problem connect.microsoft.com on web.archive.org and I downloaded an ran the AtomMonitor from JordiCorbilla/atom-table-monitor (GitHub). Indeed I found an increasing number of RWM Atoms created by my application over time (approx 4000 after some days). This fits to the exception message. All strings look like the following:

C1FE = HwndWrapper[XY.exe;;b68ce81a-d29f-414b-b63a-3b6979e33dd3]  --RWM

From the exception message I see that a 'Popup' is causing a RegisterClassEx from within the OnIsOpenChanged method.

However, opening and closing several popups in my application and monitoring the count of RWM atoms in parallel, I can't see any increase, that's why I can't find the exact source of the problem. Just after some time, when looking at the statistics again I can see that the count increased.

So my questions are:

  1. Can a Popup be responsible for raising the count of RWM atoms? If yes, is this a bug? Why does it create a new Window and registers these atoms?

  2. Do I use the Popup in a wrong way? Do I have to close/dispose/release something?

  3. Is the Popup the problem at all?

  4. What is the 'normal' number of RWM atoms an application creates or should not exceed, because as far as I know they can't be deleted anymore.

1
This problem likely has nothing to do with C# or WPF. It is based on the COM technology. A bit of a predecessors of .NET, it has some additional issues and limitations. I added the tag to represent that.Christopher
Please translate the stack into english. @Christopher - where do you see COM in there?Simon Mourier
Just because the exception popped up when calling RegisterClassEx does not mean that this method is responsible for the leak. It was the straw that broke the camel's back (German: Es war der Tropfen, der das Fass zum Überlaufen brachte). Make sure to Dispose all disposable objects (either explicitly or with the using statement)!Olivier Jacot-Descombes
@SimonMourier System.ComponentModel.Win32Exception. Also "Not enough storage is available to process this command" when we already have a Out of Memory Exception for anything like that from Managed. So it definitely does not relate to Managed Code OOM's.Christopher
@SimonMourier I updated the post with the translationCreepin

1 Answers

1
votes

After some research, I found the following: It was not related to popups or any "real" windows. Besides that, closing a popup releases the entry from the atom table.

The cause is: We create WriteableBitmaps on different tasks for image processing. Always when a new thread is used for this task (creating a WPF control), a Dispatcher gets created which in turn creates a HwndWrapper.

These resources are not released, if the dispatcher is not shutdown manually. Now we use the workaround from the following links:

GitHub: Win32Exception is thrown when WPF runs out of internal resources

SO: Why does LongRunning task (TPL) with JpegBitmapDecoder run out of resources?

Microsoft Connect: System.ComponentModel.Win32Exception (0x80004005): Not enough storage is available to process this command

SO: Resource leak when creating freezable objects in a background thread