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 738868 - Memory leak under Windows 7 if gtk_widget_modify_font used
Memory leak under Windows 7 if gtk_widget_modify_font used
Status: RESOLVED FIXED
Product: pango
Classification: Platform
Component: win32
1.36.x
Other Windows
: Normal normal
: ---
Assigned To: gtk-win32 maintainers
pango-maint
: 745695 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2014-10-20 13:21 UTC by Max
Modified: 2015-03-24 18:45 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
source code of application what reproduce mem leak under Windows 7 (2.64 KB, text/plain)
2014-10-20 13:21 UTC, Max
  Details
Fix weak pointer leak (564 bytes, patch)
2014-10-22 07:07 UTC, Max
committed Details | Review
Increase MAX_FREED_FONTS value (480 bytes, patch)
2014-10-22 07:19 UTC, Max
committed Details | Review

Description Max 2014-10-20 13:21:52 UTC
Created attachment 288941 [details]
source code of application what reproduce mem leak under Windows 7

During searching for memory leak in my application i discovered that leak
happens only under Windows 7 X64 (no Window XP 64 bit, nor Linux x64).

Leak appear if label widget been has modified font with gtk_widget_modify_font.

I created minimal test application that demonstrate leak. Each text update on
label cause a mem usage grow. Mem grow become faster if affinity changed on
executable process to one CPU.

Removing gtk_widget_modify_font from code fix situation.

gtk+-2.24.24 and pango-1.36.8 is used.
Comment 1 Max 2014-10-20 13:35:51 UTC
i did some tests with umdh and found that mem leak happens in pango. here is a diff of umdh output:

+ 78a9f70 ( 7d12060 - 4680f0)      1 allocs	BackTrace4CFF760
+       0 (     1 -     1)	BackTrace4CFF760	allocations

	ntdll!RtlWow64EnableFsRedirection+0000E588
	msvcrt!realloc+00000052
	libglib-2.0-0!g_realloc+00000036
	libgobject-2.0-0!g_object_weak_ref+0000007E
	libpangocairo-1.0-0!pango_cairo_error_underline_path+00000583
	libpangowin32-1.0-0!pango_win32_font_cache_unload+0000143F
	libpangowin32-1.0-0!pango_win32_font_cache_unload+0000153A
	libpango-1.0-0!pango_color_parse+00000F21
	libpango-1.0-0!pango_itemize_with_base_dir+00000108
	libpango-1.0-0!pango_layout_line_get_extents+000006E9
	libpango-1.0-0!pango_layout_move_cursor_visually+0000068D
	libgtk-win32-2.0-0!gtk_label_get_angle+00001C38
	libgobject-2.0-0!g_cclosure_marshal_VOID__BOXEDv+0000004C
	libgobject-2.0-0!g_closure_invoke+000002D0
	libgobject-2.0-0!g_signal_emit_valist+00000715
	libgobject-2.0-0!g_signal_emit_by_name+0000045F
	libgtk-win32-2.0-0!gtk_size_group_get_widgets+00000118
	libgtk-win32-2.0-0!gtk_box_get_type+00000823
	libgobject-2.0-0!g_cclosure_marshal_VOID__BOXEDv+0000004C
	libgobject-2.0-0!g_closure_invoke+000002D0
	libgobject-2.0-0!g_signal_emit_valist+00000715
	libgobject-2.0-0!g_signal_emit_by_name+0000045F
	libgtk-win32-2.0-0!gtk_size_group_get_widgets+00000118
	libgtk-win32-2.0-0!gtk_decorated_window_move_resize_window+000015BE
	libgobject-2.0-0!g_cclosure_marshal_VOID__BOXEDv+0000004C
	libgobject-2.0-0!g_closure_invoke+0000038D
	libgobject-2.0-0!g_signal_emit_valist+00000715
	libgobject-2.0-0!g_signal_emit_by_name+0000045F
	libgtk-win32-2.0-0!gtk_size_group_get_widgets+00000118
	libgtk-win32-2.0-0!gtk_decorated_window_move_resize_window+00001EA9
	libgtk-win32-2.0-0!gtk_decorated_window_move_resize_window+00002575
	libgobject-2.0-0!g_closure_invoke+0000038D

and it grows.

line that cause a leak in pangocairo-win32font.c seems is:
[...]
  g_object_add_weak_pointer (G_OBJECT (win32font->fontmap), (gpointer *) (gpointer) &win32font->fontmap);
[...]
rather then gdb calc:
[...]
(gdb) break *(pango_cairo_error_underline_path+0x00000583)
Breakpoint 1 at 0x6d4c5ad3: file ../../pango/pangocairo-win32font.c, line 259.
(gdb)
[...]
which is
[...]
  face->cached_fonts = g_slist_prepend (face->cached_fonts, win32font);
[...]

i did some gdb backtrace and it looks like:

(gdb)
  • #0 _pango_cairo_win32_font_new
    at ../../pango/pangocairo-win32font.c line 259
  • #1 pango_win32_font_map_fontset_add_fonts
    at ../../pango/pangowin32-fontmap.c line 705
  • #2 pango_win32_font_map_load_fontset
    at ../../pango/pangowin32-fontmap.c line 1700
  • #3 itemize_state_update_for_new_run
    at ../../pango/pango-context.c line 1433
  • #4 itemize_state_process_run
    at ../../pango/pango-context.c line 1472
  • #5 pango_itemize_with_base_dir
    at ../../pango/pango-context.c line 1611
  • #6 pango_layout_check_lines
    at ../../pango/pango-layout.c line 3998
  • #7 pango_layout_get_extents_internal
    at ../../pango/pango-layout.c line 2587
  • #8 gtk_label_size_request
    at ../../gtk/gtklabel.c line 3179
  • #9 g_cclosure_marshal_VOID__BOXEDv
    at ../../gobject/gmarshal.c line 1160
  • #10 _g_closure_invoke_va
    at ../../gobject/gclosure.c line 831
  • #11 g_signal_emit_valist
    at ../../gobject/gsignal.c line 3218
  • #12 g_signal_emit_by_name
    at ../../gobject/gsignal.c line 3405
  • #13 do_size_request
    at ../../gtk/gtksizegroup.c line 831
  • #14 _gtk_size_group_compute_requisition
    at ../../gtk/gtksizegroup.c line 828
  • #15 gtk_box_size_request
    at ../../gtk/gtkbox.c line 280
  • #16 g_cclosure_marshal_VOID__BOXEDv
    at ../../gobject/gmarshal.c line 1160
  • #17 _g_closure_invoke_va
    at ../../gobject/gclosure.c line 831
  • #18 g_signal_emit_valist
    at ../../gobject/gsignal.c line 3218
  • #19 g_signal_emit_by_name
    at ../../gobject/gsignal.c line 3405
  • #20 do_size_request
    at ../../gtk/gtksizegroup.c line 831
  • #21 _gtk_size_group_compute_requisition
    at ../../gtk/gtksizegroup.c line 828
  • #22 gtk_window_size_request
    at ../../gtk/gtkwindow.c line 4968
  • #23 g_cclosure_marshal_VOID__BOXEDv
    at ../../gobject/gmarshal.c line 1160
  • #24 _g_closure_invoke_va
    at ../../gobject/gclosure.c line 831
  • #25 g_signal_emit_valist
    at ../../gobject/gsignal.c line 3218
  • #26 g_signal_emit_by_name
    at ../../gobject/gsignal.c line 3405
  • #27 do_size_request
    at ../../gtk/gtksizegroup.c line 831
  • #28 _gtk_size_group_compute_requisition
    at ../../gtk/gtksizegroup.c line 828
  • #29 gtk_window_compute_configure_request
    at ../../gtk/gtkwindow.c line 5842
  • #30 gtk_window_move_resize
    at ../../gtk/gtkwindow.c line 6054
  • #31 gtk_window_check_resize
    at ../../gtk/gtkwindow.c line 5408
  • #32 _g_closure_invoke_va
    at ../../gobject/gclosure.c line 831
  • #33 g_signal_emit_valist
    at ../../gobject/gsignal.c line 3218
  • #34 g_signal_emit
    at ../../gobject/gsignal.c line 3365
  • #35 gtk_container_idle_sizer
    at ../../gtk/gtkcontainer.c line 1357
  • #36 gdk_threads_dispatch
    at ../../gdk/gdk.c line 512
  • #37 g_main_dispatch
    at ../../glib/gmain.c line 3111
  • #38 g_main_context_dispatch
    at ../../glib/gmain.c line 3710
  • #38 g_main_context_dispatch
    at ../../glib/gmain.c line 3710
  • #39 g_main_context_iterate
    at ../../glib/gmain.c line 3781
  • #40 g_main_loop_run
    at ../../glib/gmain.c line 3975
  • #41 gtk_main
    at ../../gtk/gtkmain.c line 1257
  • #42 main
    at test1.c line 117

it seems that creating some labels with different font cause running *itemize_state_update_for_new_run* each time then labels need to be redrawed, moreover it seems that USE_FACE_CACHED_FONTS code parts not working properly...
Comment 2 Max 2014-10-22 07:04:26 UTC
i found that problem cased by line in pangocairo-win32font.c
[...]
  g_object_add_weak_pointer (G_OBJECT (win32font->fontmap), (gpointer *) (gpointer) &win32font->fontmap);
[...]

because of *pango_win32_font_finalize* does not remove that weak leak in pangowin32.c:
[...]
  fontmap = g_weak_ref_get ((GWeakRef *) &win32font->fontmap);
  if (fontmap)
    g_object_unref (fontmap);
[...]

to fix leak it should looks like:

[...]
  fontmap = g_weak_ref_get ((GWeakRef *) &win32font->fontmap);
  if (fontmap)
  {
    g_object_remove_weak_pointer (G_OBJECT (win32font->fontmap), (gpointer *) (gpointer) &win32font->fontmap);
    g_object_unref (fontmap);
  }
[...]

patch will be attached
Comment 3 Max 2014-10-22 07:07:18 UTC
Created attachment 289102 [details] [review]
Fix weak pointer leak

This patch fix leak with lost weak references in fontset
Comment 4 Max 2014-10-22 07:17:06 UTC
i was also trying to resolve why does it happens on Windows 7.

i think it happens because of a lot of fonts installed in system that aliased with *Monospace*. it seems asking for font-desc "Monospace 14" will crease a tons of aliases like:
    courier new
    lucida console
    courier monothai
    mingliu
    simsun
    gulimche

in the same time fontset's cache is limited:

#define MAX_FREED_FONTS 16

that cause cache overflow and further cache miss for next font request, so i suggest to extend MAX_FREED_FONTS value to 256 or 1024 that will make cache size enough for keeping all aliases font there

so in my case pango does miss all cache requests because of small cache and long aliases list. so it have to create font each time it need to be redrawed:

(gdb) bt
  • #0 pango_win32_font_finalize
    at ../../pango/pangowin32.c line 851
  • #1 g_object_unref
    at ../../gobject/gobject.c line 3170
  • #2 pango_win32_fontmap_cache_add
    at ../../pango/pangowin32.c line 787
  • #3 pango_win32_font_dispose
    at ../../pango/pangowin32.c line 805
  • #4 g_object_unref
    at ../../gobject/gobject.c line 3133
  • #5 pango_fontset_simple_finalize
    at ../../pango/pango-fontset.c line 286
  • #6 g_object_unref
    at ../../gobject/gobject.c line 3170
  • #7 itemize_state_finish
    at ../../pango/pango-context.c line 1560
  • #8 pango_itemize_with_base_dir
    at ../../pango/pango-context.c line 1614
  • #9 pango_layout_check_lines
    at ../../pango/pango-layout.c line 3998
  • #10 pango_layout_get_extents_internal
    at ../../pango/pango-layout.c line 2587
  • #11 gtk_label_size_request
    at ../../gtk/gtklabel.c line 3179
  • #12 g_cclosure_marshal_VOID__BOXEDv
    at ../../gobject/gmarshal.c line 1160
  • #13 _g_closure_invoke_va
    at ../../gobject/gclosure.c line 831
  • #14 g_signal_emit_valist
    at ../../gobject/gsignal.c line 3218
  • #15 g_signal_emit_by_name
    at ../../gobject/gsignal.c line 3405
  • #16 do_size_request
    at ../../gtk/gtksizegroup.c line 831
  • #17 _gtk_size_group_compute_requisition
    at ../../gtk/gtksizegroup.c line 828
  • #18 gtk_box_size_request
    at ../../gtk/gtkbox.c line 280
  • #19 g_cclosure_marshal_VOID__BOXEDv
    at ../../gobject/gmarshal.c line 1160
  • #20 _g_closure_invoke_va
    at ../../gobject/gclosure.c line 831
  • #21 g_signal_emit_valist
    at ../../gobject/gsignal.c line 3218
  • #22 g_signal_emit_by_name
    at ../../gobject/gsignal.c line 3405
  • #23 do_size_request
    at ../../gtk/gtksizegroup.c line 831
  • #24 _gtk_size_group_compute_requisition
    at ../../gtk/gtksizegroup.c line 828
  • #25 gtk_window_size_request
    at ../../gtk/gtkwindow.c line 4968
  • #26 g_cclosure_marshal_VOID__BOXEDv
    at ../../gobject/gmarshal.c line 1160
  • #27 _g_closure_invoke_va
    at ../../gobject/gclosure.c line 831
  • #28 g_signal_emit_valist
    at ../../gobject/gsignal.c line 3218
  • #29 g_signal_emit_by_name
    at ../../gobject/gsignal.c line 3405
  • #30 do_size_request
    at ../../gtk/gtksizegroup.c line 831
  • #31 _gtk_size_group_compute_requisition
    at ../../gtk/gtksizegroup.c line 828
  • #32 gtk_window_compute_configure_request
    at ../../gtk/gtkwindow.c line 5842
  • #33 gtk_window_move_resize
    at ../../gtk/gtkwindow.c line 6054
  • #34 gtk_window_check_resize
    at ../../gtk/gtkwindow.c line 5408
  • #35 _g_closure_invoke_va
    at ../../gobject/gclosure.c line 831
  • #36 g_signal_emit_valist
    at ../../gobject/gsignal.c line 3218
  • #37 g_signal_emit
    at ../../gobject/gsignal.c line 3365
  • #38 gtk_container_idle_sizer
    at ../../gtk/gtkcontainer.c line 1357
  • #39 gdk_threads_dispatch
    at ../../gdk/gdk.c line 512
  • #40 g_main_dispatch
    at ../../glib/gmain.c line 3111
  • #41 g_main_context_dispatch
    at ../../glib/gmain.c line 3710
  • #42 g_main_context_iterate
    at ../../glib/gmain.c line 3781
  • #43 g_main_loop_run
    at ../../glib/gmain.c line 3975
  • #44 gtk_main
    at ../../gtk/gtkmain.c line 1257
  • #45 main
    at test1.c line 117

Comment 5 Max 2014-10-22 07:19:01 UTC
Created attachment 289104 [details] [review]
Increase MAX_FREED_FONTS value

Increasing MAX_FREED_FONTS value should make fontset's cache working on normal mode because of long aliases list and available fonts under Windows 7
Comment 6 Behdad Esfahbod 2014-10-26 23:10:27 UTC
Both patches look good to me.  Have not tested.
Comment 7 Matthias Clasen 2014-12-05 02:26:15 UTC
Attachment 289102 [details] pushed as 92a4e7b - Fix weak pointer leak
Attachment 289104 [details] pushed as a533850 - Increase MAX_FREED_FONTS value
Comment 8 Behdad Esfahbod 2015-03-23 22:40:26 UTC
*** Bug 745695 has been marked as a duplicate of this bug. ***
Comment 9 Matthias Clasen 2015-03-24 11:39:38 UTC
Well, I bumped master to 1.37 because you wanted to kill modules and do some other actual development... sadly, it didn't happen.

So, I may just cherry-pick a few bug fixes to the 1.36 branch and leave it at that
Comment 10 Behdad Esfahbod 2015-03-24 18:45:00 UTC
Umm.  Sorry about that.  Just put some time aside to do that next week.  A maintenance branch might be useful in the mean time.  Thanks again.