[alsa-devel] ALSA Leaking memory
Hi!
Apparently alsa-libs .15 is leaking memory when using snd_pcm_open() on some devices that cannot be opened.
On my USB wecam which has only a single mono audio stream, opening it as "front:3" (which of course fails) leaks a bit of memory. Consider this example:
<snip> #include <asoundlib.h> #include <assert.h>
int main(int argc, char *argv[]) { snd_pcm_t *pcm;
if (snd_pcm_open(&pcm, "front:3", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) == 0) { int r = snd_pcm_close(pcm); assert(r == 0); }
snd_config_update_free_global(); return 0; } </snip>
And there they are gone, the 10 bytes of memory. Here's a snippet from valgrinding this program:
==22198== 10 bytes in 1 blocks are definitely lost in loss record 1 of 3 ==22198== at 0x4023765: malloc (vg_replace_malloc.c:149) ==22198== by 0x417C44F: strdup (strdup.c:43) ==22198== by 0x4071954: snd_determine_driver (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406E80C: snd_config_hook_load_for_all_cards (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406EC7C: (within /usr/lib/libasound.so.2.0.0) ==22198== by 0x406F896: snd_config_searcha_hooks (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406FA74: snd_config_search_alias_hooks (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406FCD9: snd_config_search_definition (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x40952FE: (within /usr/lib/libasound.so.2.0.0) ==22198== by 0x80484D7: main (in /home/lennart/alsa-test)
And there seem to be more. When PulseAudio starts up it probes for available audio devices. On my machine there are 5 sound cards, which are all probed with device strings like "surround51:0" and so on, and in the end some memory with a caller history like the one shown above is shown, and another one:
==22229== 235 (180 direct, 55 indirect) bytes in 5 blocks are definitely lost in loss record 6 of 6 ==22229== at 0x4023AA4: calloc (vg_replace_malloc.c:279) ==22229== by 0x46967B8: (within /usr/lib/libasound.so.2.0.0) ==22229== by 0x4696C48: snd_config_make (in /usr/lib/libasound.so.2.0.0) ==22229== by 0x4696CD0: snd_config_imake_pointer (in /usr/lib/libasound.so.2.0.0) ==22229== by 0x46EA573: _snd_pcm_hook_ctl_elems_install (in /usr/lib/libasound.so.2.0.0) ==22229== by 0x46EAC10: (within /usr/lib/libasound.so.2.0.0) ==22229== by 0x46EB2BC: _snd_pcm_hooks_open (in /usr/lib/libasound.so.2.0.0) ==22229== by 0x46C0CD4: (within /usr/lib/libasound.so.2.0.0) ==22229== by 0x46C1467: snd_pcm_open_slave (in /usr/lib/libasound.so.2.0.0) ==22229== by 0x46D232B: _snd_pcm_route_open (in /usr/lib/libasound.so.2.0.0) ==22229== by 0x46C0CD4: (within /usr/lib/libasound.so.2.0.0) ==22229== by 0x46C1467: snd_pcm_open_slave (in /usr/lib/libasound.so.2.0.0) ==22229== by 0x46E47CC: _snd_pcm_empty_open (in /usr/lib/libasound.so.2.0.0) ==22229== by 0x46C0CD4: (within /usr/lib/libasound.so.2.0.0) ==22229== by 0x46C13D2: (within /usr/lib/libasound.so.2.0.0) ==22229== by 0x412E007: pa_alsa_open_by_device_id (alsa-util.c:529) ==22229== by 0x4135904: module_alsa_sink_LTX_pa__init (module-alsa-sink.c:781) ==22229== by 0x419CD2B: pa_module_load (module.c:115) ==22229== by 0x4164D33: hal_device_load_alsa (module-hal-detect.c:204) ==22229== by 0x4165313: hal_device_add (module-hal-detect.c:323)
Lennart
On Sun, 25 Nov 2007, Lennart Poettering wrote:
Hi!
Apparently alsa-libs .15 is leaking memory when using snd_pcm_open() on some devices that cannot be opened.
On my USB wecam which has only a single mono audio stream, opening it as "front:3" (which of course fails) leaks a bit of memory. Consider this example:
<snip> #include <asoundlib.h> #include <assert.h>
int main(int argc, char *argv[]) { snd_pcm_t *pcm;
if (snd_pcm_open(&pcm, "front:3", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK) == 0) { int r = snd_pcm_close(pcm); assert(r == 0); } snd_config_update_free_global(); return 0;
}
</snip>
And there they are gone, the 10 bytes of memory. Here's a snippet from valgrinding this program:
==22198== 10 bytes in 1 blocks are definitely lost in loss record 1 of 3 ==22198== at 0x4023765: malloc (vg_replace_malloc.c:149) ==22198== by 0x417C44F: strdup (strdup.c:43) ==22198== by 0x4071954: snd_determine_driver (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406E80C: snd_config_hook_load_for_all_cards (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406EC7C: (within /usr/lib/libasound.so.2.0.0) ==22198== by 0x406F896: snd_config_searcha_hooks (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406FA74: snd_config_search_alias_hooks (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406FCD9: snd_config_search_definition (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x40952FE: (within /usr/lib/libasound.so.2.0.0) ==22198== by 0x80484D7: main (in /home/lennart/alsa-test)
Broken valgrind? I cannot reproduce here and from first glance, the error path in snd_config_hook_load_for_all_cards is good.
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project
On Sun, 25.11.07 22:56, Jaroslav Kysela (perex@perex.cz) wrote:
==22198== 10 bytes in 1 blocks are definitely lost in loss record 1 of 3 ==22198== at 0x4023765: malloc (vg_replace_malloc.c:149) ==22198== by 0x417C44F: strdup (strdup.c:43) ==22198== by 0x4071954: snd_determine_driver (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406E80C: snd_config_hook_load_for_all_cards (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406EC7C: (within /usr/lib/libasound.so.2.0.0) ==22198== by 0x406F896: snd_config_searcha_hooks (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406FA74: snd_config_search_alias_hooks (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406FCD9: snd_config_search_definition (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x40952FE: (within /usr/lib/libasound.so.2.0.0) ==22198== by 0x80484D7: main (in /home/lennart/alsa-test)
Broken valgrind?
Unlikely.
I cannot reproduce here and from first glance, the error path in snd_config_hook_load_for_all_cards is good.
I don't fully grok the code of that function (snd_config_hook_load_for_all_cards()), but from *my* first glance I see that snd_determine_driver() allocates the string. Immediately after that call there are at least two "continue"s which will cause immediate jumping to the next iteration of the loop this whole code lives in, without ever freeing the string.
Or am I blind or missed something?
Lennart
On Sun, 25 Nov 2007, Lennart Poettering wrote:
On Sun, 25.11.07 22:56, Jaroslav Kysela (perex@perex.cz) wrote:
==22198== 10 bytes in 1 blocks are definitely lost in loss record 1 of 3 ==22198== at 0x4023765: malloc (vg_replace_malloc.c:149) ==22198== by 0x417C44F: strdup (strdup.c:43) ==22198== by 0x4071954: snd_determine_driver (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406E80C: snd_config_hook_load_for_all_cards (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406EC7C: (within /usr/lib/libasound.so.2.0.0) ==22198== by 0x406F896: snd_config_searcha_hooks (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406FA74: snd_config_search_alias_hooks (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x406FCD9: snd_config_search_definition (in /usr/lib/libasound.so.2.0.0) ==22198== by 0x40952FE: (within /usr/lib/libasound.so.2.0.0) ==22198== by 0x80484D7: main (in /home/lennart/alsa-test)
Broken valgrind?
Unlikely.
I cannot reproduce here and from first glance, the error path in snd_config_hook_load_for_all_cards is good.
I don't fully grok the code of that function (snd_config_hook_load_for_all_cards()), but from *my* first glance I see that snd_determine_driver() allocates the string. Immediately after that call there are at least two "continue"s which will cause immediate jumping to the next iteration of the loop this whole code lives in, without ever freeing the string.
Or am I blind or missed something?
No, I'm blind (seeing and associating continue to inner while) ;-) Thanks for notice. This commit should fix the problem:
http://hg.alsa-project.org/alsa-lib/rev/c8aa952a4579
Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project
On Sun, 25.11.07 23:23, Jaroslav Kysela (perex@perex.cz) wrote:
I cannot reproduce here and from first glance, the error path in snd_config_hook_load_for_all_cards is good.
I don't fully grok the code of that function (snd_config_hook_load_for_all_cards()), but from *my* first glance I see that snd_determine_driver() allocates the string. Immediately after that call there are at least two "continue"s which will cause immediate jumping to the next iteration of the loop this whole code lives in, without ever freeing the string.
Or am I blind or missed something?
No, I'm blind (seeing and associating continue to inner while) ;-) Thanks for notice. This commit should fix the problem:
Hmm, I still don't fully grok the function, but doesn't this commit change the behaviour of the function quite a bit?
I am not sure due to what kinds of errors snd_config_get_string() or snd_config_search() might fail, but the names of those functions sound a bit like configuration errors might be one reason for the failure. Before this commit, on such an error the code would just go ahead with the next card. Now, on such an error the loop is terminated immediately. Sounds like a big change in behaviour to me.
Any idea on that other valgrind bt I posted? Some leak with snd_config_make() involved?
Lennart
On Sun, 25 Nov 2007, Lennart Poettering wrote:
On Sun, 25.11.07 23:23, Jaroslav Kysela (perex@perex.cz) wrote:
I cannot reproduce here and from first glance, the error path in snd_config_hook_load_for_all_cards is good.
I don't fully grok the code of that function (snd_config_hook_load_for_all_cards()), but from *my* first glance I see that snd_determine_driver() allocates the string. Immediately after that call there are at least two "continue"s which will cause immediate jumping to the next iteration of the loop this whole code lives in, without ever freeing the string.
Or am I blind or missed something?
No, I'm blind (seeing and associating continue to inner while) ;-) Thanks for notice. This commit should fix the problem:
Hmm, I still don't fully grok the function, but doesn't this commit change the behaviour of the function quite a bit?
I am not sure due to what kinds of errors snd_config_get_string() or snd_config_search() might fail, but the names of those functions sound a bit like configuration errors might be one reason for the failure. Before this commit, on such an error the code would just go ahead with the next card. Now, on such an error the loop is terminated immediately. Sounds like a big change in behaviour to me.
I don't see a change in behaviour. The __err section just frees only fdriver variable (private_data is NULL and err is >= 0 - see line 2896). Because card >= 0 (2896 line), while on line 2923 will continue (thus next card will be processed too). I hope I've not overlooked something, too.
Any idea on that other valgrind bt I posted? Some leak with snd_config_make() involved?
Please, give use a simple testcase. This issue might be difficult to investigate without it.
Thanks, Jaroslav
----- Jaroslav Kysela perex@perex.cz Linux Kernel Sound Maintainer ALSA Project
At Mon, 26 Nov 2007 08:17:11 +0100 (CET), Jaroslav Kysela wrote:
Any idea on that other valgrind bt I posted? Some leak with snd_config_make() involved?
Please, give use a simple testcase. This issue might be difficult to investigate without it.
Maybe this one?
Takashi
diff -r 449e65b91bb3 src/pcm/pcm_hooks.c --- a/src/pcm/pcm_hooks.c Mon Nov 26 12:29:37 2007 +0100 +++ b/src/pcm/pcm_hooks.c Mon Nov 26 12:47:10 2007 +0100 @@ -657,6 +657,7 @@ int _snd_pcm_hook_ctl_elems_install(snd_ snd_pcm_hook_ctl_elems_close, sctl); if (err < 0) goto _err; + snd_config_delete(pcm_conf); return 0; _err: if (h_hw_params)
participants (3)
-
Jaroslav Kysela
-
Lennart Poettering
-
Takashi Iwai