Comment 12 for bug 485923

Revision history for this message
Alistair Buxton (a-j-buxton) wrote :

These logs were done with --show-reachable=yes because Valgrind does not always see the memory as lost. The results are quite conclusive:

From gvca:
==12744== 122,531,944 bytes in 373,573 blocks are still reachable in loss record 6,971 of 6,971
==12744== at 0x4024C1C: malloc (vg_replace_malloc.c:195)
==12744== by 0x45972E3: g_malloc (gmem.c:131)
==12744== by 0x45AD418: g_slice_alloc (gslice.c:824)
==12744== by 0x45AD714: g_slice_alloc0 (gslice.c:833)
==12744== by 0x44FD8F6: g_type_create_instance (gtype.c:1654)
==12744== by 0x44E2747: g_object_constructor (gobject.c:1383)
==12744== by 0x44E3707: g_object_newv (gobject.c:1171)
==12744== by 0x44E4589: g_object_new_valist (gobject.c:1323)
==12744== by 0x44E470D: g_object_new (gobject.c:1086)
==12744== by 0x80515FE: gvc_channel_map_new_from_pa_channel_map (gvc-channel-map.c:287)
==12744== by 0x8057552: _pa_context_get_sink_input_info_cb (gvc-mixer-control.c:886)
==12744== by 0x452DB6C: context_get_sink_input_info_callback (introspect.c:1028)
==12744== by 0x4C6CEA4: run_action (pdispatch.c:274)
==12744== by 0x4C6D475: pa_pdispatch_run (pdispatch.c:326)
==12744== by 0x4525148: pstream_packet_callback (context.c:357)
==12744== by 0x4C726E7: do_something (pstream.c:816)
==12744== by 0x4C5D11D: callback (iochannel.c:119)
==12744== by 0x4511F32: ??? (in /usr/lib/libpulse-mainloop-glib.so.0.0.4)
==12744== by 0x458EE87: g_main_context_dispatch (gmain.c:1960)
==12744== by 0x459272F: g_main_context_iterate (gmain.c:2591)
==12744== by 0x4592B9E: g_main_loop_run (gmain.c:2799)
==12744== by 0x418D418: gtk_main (gtkmain.c:1218)
==12744== by 0x804EEF0: main (applet-main.c:92)
==12744==
==12744== LEAK SUMMARY:
==12744== definitely lost: 14,792 bytes in 23 blocks
==12744== indirectly lost: 19,683 bytes in 540 blocks
==12744== possibly lost: 46,340 bytes in 1,836 blocks
==12744== still reachable: 157,160,155 bytes in 1,524,594 blocks
==12744== suppressed: 11,664 bytes in 266 blocks

And in gsd:

==12804== 122,420,096 bytes in 373,232 blocks are possibly lost in loss record 5,433 of 5,433
==12804== at 0x4024C1C: malloc (vg_replace_malloc.c:195)
==12804== by 0x48702E3: g_malloc (gmem.c:131)
==12804== by 0x4886418: g_slice_alloc (gslice.c:824)
==12804== by 0x4886714: g_slice_alloc0 (gslice.c:833)
==12804== by 0x481C8F6: g_type_create_instance (gtype.c:1654)
==12804== by 0x4801747: g_object_constructor (gobject.c:1383)
==12804== by 0x4802707: g_object_newv (gobject.c:1171)
==12804== by 0x4803589: g_object_new_valist (gobject.c:1323)
==12804== by 0x480370D: g_object_new (gobject.c:1086)
==12804== by 0x651BA2E: gvc_channel_map_new_from_pa_channel_map (gvc-channel-map.c:287)
==12804== by 0x6521382: _pa_context_get_sink_input_info_cb (gvc-mixer-control.c:886)
==12804== by 0x5CF2B6C: context_get_sink_input_info_callback (introspect.c:1028)
==12804== by 0x5D41EA4: run_action (pdispatch.c:274)
==12804== by 0x5D42475: pa_pdispatch_run (pdispatch.c:326)
==12804== by 0x5CEA148: pstream_packet_callback (context.c:357)
==12804== by 0x5D476E7: do_something (pstream.c:816)
==12804== by 0x5D3211D: callback (iochannel.c:119)
==12804== by 0x5CD7F32: ??? (in /usr/lib/libpulse-mainloop-glib.so.0.0.4)
==12804== by 0x4867E87: g_main_context_dispatch (gmain.c:1960)
==12804== by 0x486B72F: g_main_context_iterate (gmain.c:2591)
==12804== by 0x486BB9E: g_main_loop_run (gmain.c:2799)
==12804== by 0x417A418: gtk_main (gtkmain.c:1218)
==12804== by 0x804B9AD: main (main.c:489)
==12804==
==12804== LEAK SUMMARY:
==12804== definitely lost: 7,376 bytes in 584 blocks
==12804== indirectly lost: 28,244 bytes in 2,353 blocks
==12804== possibly lost: 149,360,130 bytes in 1,495,604 blocks
==12804== still reachable: 7,059,820 bytes in 13,284 blocks
==12804== suppressed: 9,360 bytes in 221 blocks

gvc_channel_map_new_from_pa_channel_map allocates a channel map every time an applications creates a pulseaudio sink. The map ends up stored in a hash table (in update_sink_input in gvc-mixer-control.c). When the application closes the sink, the channel map is not freed. Eventually the hash table grows very large. This is made far worse by misbehaving apps which open and close the sink repeatedly, such as in my video. Valgrind does not see the memory as lost because it is still reachable through the hash table.