Black wi(n)dow

Hello, 64-bit memory consumption is scary, even if the program does not crash as fast as 32-bit.
After a certain number of open and closed windows, a window opens all black and the user session of the Mac closes!
We have this problem with some of our customers and we do not see what to do -> thank you for helping us.

This sounds like <https://xojo.com/issue/34956> which was never reopened or <https://xojo.com/issue/45697> which was not reviewed. Maybe adding some points could help to get this bug into the engineers’ sight.
I try in projects which use multiple windows to simply hide them instead of closing and reopening.

EDIT: I just noticed that the latter was a private case as it was issued during 2016r4 beta. I requested to make it public now. It is just an addition to the first when I found that the memory leak on Retina for a closed Window is about 4 MB instead of 1 for low-res screens.

Thank you Ulrich, we also thought to hide the windows instead of closing them, but it makes us rewrite a lot of code and after a few days of testing we have not reached a satisfactory solution.
It would be a big job to change everything in our program, and we would hope that Xojo corrects this memory problem!

I had forgotten : MacOS X 10.13.3, Retina 27", Xojo 2017r3

Thank you for bringing that topic up! I had forgotten about it and created a private feedback now as a reminder.

[quote=381211:@Marc COURAUD]Hello, 64-bit memory consumption is scary, even if the program does not crash as fast as 32-bit.
After a certain number of open and closed windows, a window opens all black and the user session of the Mac closes!
We have this problem with some of our customers and we do not see what to do -> thank you for helping us.[/quote]
How many windows are you talking about here? And how quickly do you run out of RAM?

Hi Greg, here a program : http://www.8sens.com/CLIENT/Wincrash.xojo_binary_project.zip

Click on the Go button: in the window title is displayed the memory used by the program.
In 32 bits, the program crashes after 4 or 5 times “Go” :
In 64 bits, you need many more windows open and closed, but it ends in crash session !

That is a lot of windows though, more than I’d expect a user to ever create in a single run of an application.

When the window is not filled as in the example, it takes a long time to plant … if it is full of controls it comes much faster!
The goal is to help Xojo correct this memory leak, in 64 bits it does “almost” not crash, indeed it needs too many windows.

(Updated: I hit Post too soon)

I made a couple of small changes to the project so it’s easier to debug.

Tested with Xojo 2017 R3 (and also the latest beta)

I ran the test on Windows 10 1803:

  • 32 bit - peak memory use is 7.0MB
  • 64 bit - peak memory use is 7.0MB

No crashes, no memory leaks.

On macOS 10.12.6

  • 32 bit - it does seem to leak about 250MB (roughly 3MB per window opened?) I don’t see a crash until about 750 windows were opened.
  • 64 bit - similar leak, but I got tired of clicking the button.

revised source: http://xochi.com/mike/rb/Wincrash2.xojo_binary_project.zip

I believe the issue is specific to Mac. Running your modified project I get 682MB of memory still being used after the third round and all the windows are closed.

(updated my results - see above)

It’s not impossible - I have an app which uses windows for doing animation with overlay layers, so it creates and destroys a lot of them over time if left running.

Now, is using windows in that way a good idea? Probably not. But seems like a bug that should be fixed.

[quote=381272:@Michael Diehr]On macOS 10.12.6
32 bit - it does seem to leak about 250MB (roughly 3MB per window opened?) I don’t see a crash until about 750 windows were[/quote]

Some of that is OS level caching, by default your Window will get it’s contents cached into RAM and into the GPU (it’s in RAM also incase the memory is needed by the GPU). If you enable layer backed views, I would expect it to increase further (control level caching). I have seen, but I have not tried options for manually assuming control of the backing store, perhaps when I have a moment I could look into it and maybe see if there’s a way it can be forcefully released upon the window closure.

Although in saying all of this I find it hard to believe, that Apple wouldn’t already flush the cache upon window tear down. It seems like that’s going to be a cause of problems for all applications. Maybe I am wrong.

I just ran this test:

  • open the test app (but don’t click the button)
  • Open Instruments on 10.12.6. Select the Leaks instrument.
  • Attach it to the test app
  • click the “Go” button, let it run, then close all the windows.
  • back in Instruments, hit Pause then click the right arrow on the VM CG Backing Stores line.

Results of leak:

  • 110 objects leaked,
  • Category: VM: CG backing stores
  • Size:, 3.86 MiB
  • Library: SkyLight
  • Responsible Caller: backing_map
  • Stack Trace:
   1 SkyLight backing_map
   2 SkyLight lock_window_backing
   3 SkyLight SLSDeviceLock
   4 CoreGraphics ripd_Lock
   5 CoreGraphics RIPLayerBltImage
   6 CoreGraphics ripc_RenderImage
   7 CoreGraphics ripc_DrawImages
   8 CoreGraphics CGContextDrawImages
   9 CoreUI _CUITileImageWithOperation
  10 CoreUI DrawOnePartElementFromRenditionWithOperation
  11 CoreUI -[CUIThemeFacet _drawSpecificRenditionKey:rendition:inFrame:context:alpha:operation:isFocused:isFlipped:effects:]
  12 CoreUI -[CUIThemeFacet _drawSpecificRenditionKey:inFrame:context:isFocused:isFlipped:effects:]
  13 CoreUI -[CUIThemeFacet drawInFrame:isFocused:context:]
  14 CoreUI CUICoreThemeRenderer::DrawWindowFrameStandardNew(CUIDescriptor const*)
  15 CoreUI CUIRenderer::Draw(CGRect, CGContext*, __CFDictionary const*, __CFDictionary const**)
  16 CoreUI CUIDraw
  17 AppKit __44-[NSAppearance _drawInRect:context:options:]_block_invoke
  18 AppKit -[NSAppearance _callCoreUIWithBlock:options:]
  19 AppKit -[NSCompositeAppearance _callCoreUIWithBlock:options:]
  20 AppKit -[NSAppearance _drawInRect:context:options:]
  21 AppKit _NSDrawThemeBackground
  22 AppKit -[NSThemeFrame _drawUnifiedToolbarWithState:inFrame:]
  23 AppKit -[NSThemeFrame _drawUnifiedToolbar:]
  24 AppKit -[NSThemeFrame _drawTitleBarBackgroundInClipRect:]
  25 AppKit -[NSThemeFrame _drawTitleBar:]
  26 AppKit -[NSThemeFrame _drawFrameInterior:clip:]
  27 AppKit -[NSThemeFrame drawFrame:]
  28 AppKit -[NSFrameView drawRect:]
  29 AppKit -[NSThemeFrame drawRect:]
  30 AppKit -[NSView _drawRect:clip:]
  31 AppKit -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
  32 AppKit -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
  33 AppKit -[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
  34 AppKit -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
  35 AppKit -[NSView displayIfNeeded]
  36 AppKit -[NSWindow displayIfNeeded]
  37 AppKit -[NSWindow _doWindowWillBeVisibleAsSheet:]
  38 AppKit -[NSWindow _reallyDoOrderWindowAboveOrBelow:relativeTo:findKey:forCounter:force:isModal:]
  39 AppKit -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:]
  40 AppKit -[NSWindow _doOrderWindowWithoutAnimation:relativeTo:findKey:forCounter:force:isModal:]
  41 AppKit -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:]
  42 AppKit -[NSWindow orderWindow:relativeTo:]
  43 AppKit -[NSWindow makeKeyAndOrderFront:]
  44 XojoFramework 0x359818
  45 XojoFramework WindowImpCocoa::ShowWindow()
  46 XojoFramework Window::SelectWindow()
  47 XojoFramework RuntimeShowWindow
  48 Wincrash Window.Show%%o<Window>
  49 Wincrash MyWin.MyWin.CreatDaughter%%o<MyWin.MyWin>o<MyWin.MyWin>i4
  50 Wincrash Window1.Window1.PushButton1_Action%%o<Window1.Window1>o<PushButton>

I hope this is enough info for Xojo folks to diagnose & fix?

So it is the backing store that’s leaking, which is the window buffer.

[quote=381387:@Michael Diehr]I just ran this test:

  • open the test app (but don’t click the button)
  • Open Instruments on 10.12.6. Select the Leaks instrument.
  • Attach it to the test app
  • click the “Go” button, let it run, then close all the windows.
  • back in Instruments, hit Pause then click the right arrow on the VM CG Backing Stores line.

Results of leak:

  • 110 objects leaked,
  • Category: VM: CG backing stores
  • Size:, 3.86 MiB
  • Library: SkyLight
  • Responsible Caller: backing_map
  • Stack Trace:
   1 SkyLight backing_map
   2 SkyLight lock_window_backing
   3 SkyLight SLSDeviceLock
   4 CoreGraphics ripd_Lock
   5 CoreGraphics RIPLayerBltImage
   6 CoreGraphics ripc_RenderImage
   7 CoreGraphics ripc_DrawImages
   8 CoreGraphics CGContextDrawImages
   9 CoreUI _CUITileImageWithOperation
  10 CoreUI DrawOnePartElementFromRenditionWithOperation
  11 CoreUI -[CUIThemeFacet _drawSpecificRenditionKey:rendition:inFrame:context:alpha:operation:isFocused:isFlipped:effects:]
  12 CoreUI -[CUIThemeFacet _drawSpecificRenditionKey:inFrame:context:isFocused:isFlipped:effects:]
  13 CoreUI -[CUIThemeFacet drawInFrame:isFocused:context:]
  14 CoreUI CUICoreThemeRenderer::DrawWindowFrameStandardNew(CUIDescriptor const*)
  15 CoreUI CUIRenderer::Draw(CGRect, CGContext*, __CFDictionary const*, __CFDictionary const**)
  16 CoreUI CUIDraw
  17 AppKit __44-[NSAppearance _drawInRect:context:options:]_block_invoke
  18 AppKit -[NSAppearance _callCoreUIWithBlock:options:]
  19 AppKit -[NSCompositeAppearance _callCoreUIWithBlock:options:]
  20 AppKit -[NSAppearance _drawInRect:context:options:]
  21 AppKit _NSDrawThemeBackground
  22 AppKit -[NSThemeFrame _drawUnifiedToolbarWithState:inFrame:]
  23 AppKit -[NSThemeFrame _drawUnifiedToolbar:]
  24 AppKit -[NSThemeFrame _drawTitleBarBackgroundInClipRect:]
  25 AppKit -[NSThemeFrame _drawTitleBar:]
  26 AppKit -[NSThemeFrame _drawFrameInterior:clip:]
  27 AppKit -[NSThemeFrame drawFrame:]
  28 AppKit -[NSFrameView drawRect:]
  29 AppKit -[NSThemeFrame drawRect:]
  30 AppKit -[NSView _drawRect:clip:]
  31 AppKit -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:]
  32 AppKit -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
  33 AppKit -[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
  34 AppKit -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
  35 AppKit -[NSView displayIfNeeded]
  36 AppKit -[NSWindow displayIfNeeded]
  37 AppKit -[NSWindow _doWindowWillBeVisibleAsSheet:]
  38 AppKit -[NSWindow _reallyDoOrderWindowAboveOrBelow:relativeTo:findKey:forCounter:force:isModal:]
  39 AppKit -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:]
  40 AppKit -[NSWindow _doOrderWindowWithoutAnimation:relativeTo:findKey:forCounter:force:isModal:]
  41 AppKit -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:]
  42 AppKit -[NSWindow orderWindow:relativeTo:]
  43 AppKit -[NSWindow makeKeyAndOrderFront:]
  44 XojoFramework 0x359818
  45 XojoFramework WindowImpCocoa::ShowWindow()
  46 XojoFramework Window::SelectWindow()
  47 XojoFramework RuntimeShowWindow
  48 Wincrash Window.Show%%o<Window>
  49 Wincrash MyWin.MyWin.CreatDaughter%%o<MyWin.MyWin>o<MyWin.MyWin>i4
  50 Wincrash Window1.Window1.PushButton1_Action%%o<Window1.Window1>o<PushButton>

I hope this is enough info for Xojo folks to diagnose & fix?[/quote]
All it needs now is a bug report in Feedback.

Looks like the graphics context is not released.
I tried this as last lines of the close event:

Declare Function graphicsContext Lib "AppKit" selector "graphicsContext" (id As Integer) As ptr Dim context As ptr =graphicsContext(Me.Handle) Declare Sub release Lib "Foundation" selector "release" (id As ptr) release context
and could find no leak anymore.

EDIT: No. That clears the Runtime.memoryUsed, but the leak persists.

Michael already did so:
<https://xojo.com/issue/45697>

Are these two reports about the same issue?
<https://xojo.com/issue/45697> Memory leak in macOS windows – 4 times as big on Retina (not ranked)
<https://xojo.com/issue/43484> window memory leak (Rank: 29th)

Does the workaround from @Carlo Rubini work here, too?

Declare Sub release Lib "Foundation" Selector "release" (receiver As Ptr) release(Ptr(Handle))

D’oh! I am surprised to see that! Yes, it still works. Or rather again.
This case was fixed, and when the bug returned I swear I tried my release fix and it did not work. :wink:
So yes, try it. Memory gets released again.
It’s of course a very dirty workaround which can crash your app if the bug is being fixed and you still have it in your app. But currently it looks ok.

I was not aware of 43484.