GNOME Bugzilla – Bug 772598
Nautilus doesn't reclaim memory from closed windows
Last modified: 2017-10-23 11:33:19 UTC
Valgrind shows nautilus is holding on to a list of closed windows, which costs about 1.4MB per closed window :(. $ rpm -q nautilus nautilus-3.20.3-1.fc24.x86_64 Methodology: `valgrind nautilus`, followed by variable number of `nautilus -w` before closing all nautilus windows. Something non-linear happened to "definitely lost" in between the #3 and #4 opened windows tests. However the bulk of the memory is counted as "still reachable", which shows a clear linear trend v.s. the number of closed windows. I ran this test after inspecting code (on master); it looked like the initially created reference to the window was simply leaked. I am not sure why valgrind is reporting them as "still reachable" instead of "lost". There are a couple of global lists of windows (in NautilusApplication and GtkApplication), but all evidence points to them correctly removing windows when closed. ## 1 window opened ## ==2684== LEAK SUMMARY: ==2684== definitely lost: 19,939 bytes in 44 blocks ==2684== indirectly lost: 27,065 bytes in 742 blocks ==2684== possibly lost: 7,016 bytes in 79 blocks ==2684== still reachable: 4,483,516 bytes in 49,892 blocks ==2684== of which reachable via heuristic: ==2684== length64 : 14,728 bytes in 220 blocks ==2684== newarray : 2,464 bytes in 74 blocks ==2684== suppressed: 0 bytes in 0 blocks ## 2 windows opened ## ==2754== LEAK SUMMARY: ==2754== definitely lost: 21,457 bytes in 118 blocks ==2754== indirectly lost: 39,346 bytes in 851 blocks ==2754== possibly lost: 7,316 bytes in 85 blocks ==2754== still reachable: 5,827,507 bytes in 67,697 blocks ==2754== of which reachable via heuristic: ==2754== length64 : 14,728 bytes in 220 blocks ==2754== newarray : 2,464 bytes in 74 blocks ==2754== suppressed: 0 bytes in 0 blocks ## 3 windows opened ## ==2955== LEAK SUMMARY: ==2955== definitely lost: 22,735 bytes in 177 blocks ==2955== indirectly lost: 51,627 bytes in 960 blocks ==2955== possibly lost: 7,616 bytes in 91 blocks ==2955== still reachable: 7,108,677 bytes in 87,434 blocks ==2955== of which reachable via heuristic: ==2955== length64 : 14,728 bytes in 220 blocks ==2955== newarray : 2,464 bytes in 74 blocks ==2955== suppressed: 0 bytes in 0 blocks ## 4 windows opened ## ==3187== LEAK SUMMARY: ==3187== definitely lost: 23,005 bytes in 173 blocks ==3187== indirectly lost: 63,908 bytes in 1,069 blocks ==3187== possibly lost: 7,916 bytes in 97 blocks ==3187== still reachable: 8,376,976 bytes in 102,785 blocks ==3187== of which reachable via heuristic: ==3187== length64 : 14,728 bytes in 220 blocks ==3187== newarray : 2,464 bytes in 74 blocks ==3187== suppressed: 0 bytes in 0 blocks ==3187== Rerun with --leak-check=full to see details of leaked memory
Correction, apparently the code I was reading was correct. GTK+ holds a (true, not floating) reference to GtkWindow objects, which should be released on gtk_widget_destroy(). And the GtkWindows must be being destroyed correctly. Otherwise, they wouldn't be removed from the lists, and the GtkApplication would not stop running. (It does, after the idle timeout). So I don't see how the windows themselves can be leaking, but something associated with them is?
First leak identified is due to gtk, not nautilus specifically. gtk_application_window_added() creates a window, `priv->help_overlay`. In application_window_dispose(), it only unrefs the window. This is incorrect; GtkWindows are special and require an explicit gtk_widget_destroy(). ==7542== 128,128 bytes in 364 blocks are still reachable in loss record 19,751 of 19,758 (364 blocks still reachable = 52 * 7. Where 7 is the number of windows I closed. Prime numbers ftw). ==7542== at 0x80BB90A: g_type_create_instance (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x809D69A: ??? (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x809F0AC: g_object_newv (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x809F863: g_object_new (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x5AD4F38: gtk_label_new (gtklabel.c:1756) ==7542== by 0x5B7CC5B: display_shortcut (gtkshortcutlabel.c:271) ==7542== by 0x5B7CC5B: parse_combination (gtkshortcutlabel.c:306) ==7542== by 0x5B7CC5B: parse_sequence (gtkshortcutlabel.c:324) ==7542== by 0x5B7D4C2: parse_range (gtkshortcutlabel.c:344) ==7542== by 0x5B7D4C2: gtk_shortcut_label_rebuild (gtkshortcutlabel.c:375) ==7542== by 0x5B7D4C2: gtk_shortcut_label_set_accelerator (gtkshortcutlabel.c:481) ==7542== by 0x809DA8C: ??? (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x809F5AD: g_object_new_valist (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x809F850: g_object_new (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x5B80A27: gtk_shortcuts_window_add_search_item (gtkshortcutswindow.c:216) ==7542== by 0x59E03A6: gtk_box_forall (gtkbox.c:2661) ==7542== by 0x5B7BE87: gtk_shortcuts_group_forall (gtkshortcutsgroup.c:186) ==7542== by 0x5B80931: gtk_shortcuts_window_add_search_item (gtkshortcutswindow.c:251) ==7542== by 0x5B7F1F7: gtk_shortcuts_section_forall (gtkshortcutssection.c:173) ==7542== by 0x5B80F40: gtk_shortcuts_window_add_section (gtkshortcutswindow.c:294) ==7542== by 0x5B80F40: gtk_shortcuts_window_add (gtkshortcutswindow.c:340) ==7542== by 0x809B46F: g_cclosure_marshal_VOID__OBJECTv (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x8098613: ??? (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x80B2DD8: g_signal_emit_valist (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x80B343E: g_signal_emit (in /usr/lib64/libgobject-2.0.so.0.4800.2) ==7542== by 0x5A26CD4: gtk_container_add (gtkcontainer.c:1875) ==7542== by 0x59E428B: _gtk_builder_add (gtkbuilder.c:873) ==7542== by 0x59EA0E0: end_element (gtkbuilderparser.c:1123) ==7542== by 0x8327DB6: ??? (in /usr/lib64/libglib-2.0.so.0.4800.2) ==7542== by 0x8328BE2: g_markup_parse_context_parse (in /usr/lib64/libglib-2.0.so.0.4800.2) ==7542== by 0x59EA355: _gtk_builder_parser_parse_buffer (gtkbuilderparser.c:1261) ==7542== by 0x59E4888: gtk_builder_add_from_resource (gtkbuilder.c:1235) ==7542== by 0x59E7C26: gtk_builder_new_from_resource (gtkbuilder.c:2608) ==7542== by 0x59CFBC2: gtk_application_window_added (gtkapplication.c:737) ==7542== by 0x1386D9: nautilus_application_window_added (nautilus-application.c:1400)
Alan, thanks for reporting and investigating this leak. Considering comment 2, should this be reassigned to gtk+?
Good point! FWIW I fixed ~600Kb of the leaks, including the leak of priv->help_overlay. I suspect I was hoping for more to be fixed. So this is really a shadow of #772859. ~700Kb of the remainder is a bug in a container class categorized under SPECIAL_CONTAINER, "containers inside GTK+ [which] are cheating". I had a patch for that too, but it hasn't been able to be reviewed sufficiently as the general arrangement "is such a disaster". This was all a year ago. (To make this a complete summary, there was apparently ~100Kb left if you applied that last patch. But I didn't write any evidence that it was a bug in nautilus). *** This bug has been marked as a duplicate of bug 772859 ***