After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 787089 - win32: GtkWindow of type GTK_WINDOW_POPUP/GDK_WINDOW_TEMP leaks memory proportional to its size
win32: GtkWindow of type GTK_WINDOW_POPUP/GDK_WINDOW_TEMP leaks memory propor...
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Backend: Win32
3.22.x
Other Windows
: Normal normal
: ---
Assigned To: gtk-win32 maintainers
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2017-08-31 15:37 UTC by Daniel Boles
Modified: 2017-12-03 03:17 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
test case (504 bytes, text/plain)
2017-08-31 15:37 UTC, Daniel Boles
  Details
test case (608 bytes, text/plain)
2017-08-31 17:37 UTC, Daniel Boles
  Details
DEBUG: track W32 GDK backend surfaces creation and destruction (8.24 KB, patch)
2017-09-04 14:44 UTC, LRN
rejected Details | Review
GDK W32: Plug a resource leak (1.40 KB, patch)
2017-09-04 14:45 UTC, LRN
none Details | Review
GDK W32: Plug a resource leak v2 (1.24 KB, patch)
2017-12-03 03:15 UTC, LRN
committed Details | Review

Description Daniel Boles 2017-08-31 15:37:46 UTC
Created attachment 358864 [details]
test case

The attached test case shows that opening and destroying GtkWindows of type GTK_WINDOW_POPUP (but not _TOPLEVEL) leaks memory.

Moreover, by increasing the size of the window, the amount of memory leaked increases proportionally, indicating the leak may be of a graphics surface or similar.


I've only just noticed this and have only been able to test it on Windows so far. Once I have access to a Linux machine, I'll confirm whether it's Windows-specific and post the results of running it under valgrind.
Comment 1 Daniel Boles 2017-08-31 17:37:45 UTC
Created attachment 358882 [details]
test case

I left TOPLEVEL in, from testing to show that prevented the leak.

When run on Linux, valgrind seems perfectly happy with this, so it seems indeed to be caused by something in the Windows backend only.


valgrind ./a.out 
==28608== Memcheck, a memory error detector
==28608== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28608== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==28608== Command: ./a.out
==28608== 
^Z^C==28608== 
==28608== Process terminating with default action of signal 2 (SIGINT)
==28608==    at 0x73EC66D: ??? (syscall-template.S:84)
==28608==    by 0x6E27118: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5306.0)
==28608==    by 0x6E274B1: g_main_loop_run (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5306.0)
==28608==    by 0x68BA905: ??? (in /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0.5306.0)
==28608==    by 0x6E4E624: ??? (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.5306.0)
==28608==    by 0x70F7493: start_thread (pthread_create.c:333)
==28608==    by 0x73F5ABE: clone (clone.S:97)
==28608== 
==28608== HEAP SUMMARY:
==28608==     in use at exit: 1,592,462 bytes in 17,053 blocks
==28608==   total heap usage: 357,813 allocs, 340,760 frees, 24,900,604 bytes allocated
==28608== 
==28608== LEAK SUMMARY:
==28608==    definitely lost: 0 bytes in 0 blocks
==28608==    indirectly lost: 0 bytes in 0 blocks
==28608==      possibly lost: 4,416 bytes in 52 blocks
==28608==    still reachable: 1,499,342 bytes in 16,285 blocks
==28608==                       of which reachable via heuristic:
==28608==                         length64           : 5,168 bytes in 86 blocks
==28608==                         newarray           : 2,096 bytes in 51 blocks
==28608==         suppressed: 0 bytes in 0 blocks
==28608== Rerun with --leak-check=full to see details of leaked memory
==28608== 
==28608== For counts of detected and suppressed errors, rerun with: -v
==28608== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Comment 2 Daniel Boles 2017-09-01 15:49:47 UTC
From LRN on irc:

dboles    LRN: Hi, do you have any guesses where to look to fix this? https://bugzilla.gnome.org/show_bug.cgi?id=787089
bugbot    Bug 787089: Backend: Win32, normal, gtk-win32-maint, NEW , win32: GtkWindow of type GTK_WINDOW_POPUP/GDK_WINDOW_TEMP leaks memory proportional to its size
LRN    dboles, i gave it some thought. What happens if you run with GDK_WIN32_LAYERED=0 ?
(running with GTK_CSD=0 probably shouldn't affect popup windows, but you might want to check that too)
dboles    LRN: thanks, I'll give those a shot once I can reboot into Windows
LRN    anyway, if the leak is proportionate to the window size, the thing leaking is most likely a surface. If i were you, i'd either hack up GDK to keep track of all surfaces it uses, or hack up cairo for the same purpose.
hacking GDK is probably easier - there aren't that many places where it allocates surfaces
and you'll be able to trivially store the source code location where that happens (if you hack that into cairo, you'd also need a backtrace library, otherwise you won't be able to find where the leaking surface is allocated)
dboles    sounds good, thanks!
Comment 3 Daniel Boles 2017-09-04 11:20:48 UTC
finally able to test this:


(In reply to Daniel Boles from comment #2)
> LRN    dboles, i gave it some thought. What happens if you run with
> GDK_WIN32_LAYERED=0 ?

Yes, indeed, this appears to stabilise the memory consumption!


> (running with GTK_CSD=0 probably shouldn't affect popup windows, but you
> might want to check that too)

This has no effect; the runaway RAM consumption continues.


> LRN    anyway, if the leak is proportionate to the window size, the thing
> leaking is most likely a surface. If i were you, i'd either hack up GDK to
> keep track of all surfaces it uses, or hack up cairo for the same purpose.
> hacking GDK is probably easier

If the effect of GDK_WIN32_LAYERED doesn't immediately suggest anything useful to you, then I can dive further into this.

I had hoped that Application Verifier or Dr Memory would report something useful, to save me the work, but no dice so far!
Comment 4 Daniel Boles 2017-09-04 11:21:15 UTC
( ping ^ )
Comment 5 LRN 2017-09-04 14:44:36 UTC
Created attachment 359083 [details] [review]
DEBUG: track W32 GDK backend surfaces creation and destruction

Seriously? It's as simple as this.
As i have said, there aren't many surfaces in W32 GDK backend, and they are
very easy to track.
Comment 6 LRN 2017-09-04 14:45:02 UTC
Created attachment 359084 [details] [review]
GDK W32: Plug a resource leak

And this patch plugs the leak that i've found.
Comment 7 Daniel Boles 2017-09-04 14:47:43 UTC
(In reply to LRN from comment #5)
> Seriously? It's as simple as this.
> As i have said, there aren't many surfaces in W32 GDK backend, and they are
> very easy to track.

Yeah, I'm sure it's insultingly simple to you. However, it's the first time I'm looking at any of the win32-specific code, having never done anything with that backend before, and I also have irregular ability to boot into Windows... so you'll have to bear with my level of ignorance for the first while!

Thanks for the effort and patches; once I'm on *another* Windows machine where I might stand a chance of building GTK+, I can test them for you.
Comment 8 LRN 2017-12-03 03:15:13 UTC
Created attachment 364838 [details] [review]
GDK W32: Plug a resource leak v2

v2:
* Remove debug code from the commit
Comment 9 LRN 2017-12-03 03:16:51 UTC
Attachment 364838 [details] pushed as 6d0b0cb - GDK W32: Plug a resource leak


Since there's been no activity in this bug, and since the patch seems rather
straightforward, i've elected to push and fix this unilaterally.