[alsa-devel] BUG: double free of PCM structure upon module removal
Takashi Iwai
tiwai at suse.de
Tue May 23 20:14:07 CEST 2017
On Tue, 23 May 2017 19:14:05 +0200,
Mark Brown wrote:
>
> On Tue, May 23, 2017 at 06:46:58PM +0200, Robert Jarzmik wrote:
>
> > Did you notice the same behavior on other platforms, and if not would you have a
> > hint why it happens to me ?
>
> This is the only report I've seen, sorry. It's not ringing any bells
> immediately either - I'll have a think.
What's the problem? soc_free_pcm_runtime() just calls kfree() of rtd,
but it's not called in snd_pcm_free(), isn't it?
In anyway the calls there look in a wrong order. Basically we should
start with snd_card_free() to sync with the whole operation finishes,
then release everything. Below is an untested patch to do that.
Takashi
---
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2047,6 +2047,8 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour)
EXPORT_SYMBOL_GPL(snd_soc_set_dmi_name);
#endif /* CONFIG_DMI */
+static void soc_cleanup_card_resources(struct snd_card *scard);
+
static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
@@ -2228,6 +2230,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
}
card->instantiated = 1;
+ card->snd_card->private_data = card;
+ card->snd_card->private_free = soc_cleanup_card_resources;
snd_soc_dapm_sync(&card->dapm);
mutex_unlock(&card->mutex);
mutex_unlock(&client_mutex);
@@ -2278,8 +2282,9 @@ static int soc_probe(struct platform_device *pdev)
return snd_soc_register_card(card);
}
-static int soc_cleanup_card_resources(struct snd_soc_card *card)
+static void soc_cleanup_card_resources(struct snd_card *scard)
{
+ struct snd_soc_card *card = scard->private_data;
struct snd_soc_pcm_runtime *rtd;
/* make sure any delayed work runs */
@@ -2299,10 +2304,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
/* remove the card */
if (card->remove)
card->remove(card);
-
- snd_card_free(card->snd_card);
- return 0;
-
}
/* removes a socdev */
@@ -2887,7 +2888,7 @@ int snd_soc_unregister_card(struct snd_soc_card *card)
if (card->instantiated) {
card->instantiated = false;
snd_soc_dapm_shutdown(card);
- soc_cleanup_card_resources(card);
+ snd_card_free(card->snd_card);
dev_dbg(card->dev, "ASoC: Unregistered card '%s'\n", card->name);
}
More information about the Alsa-devel
mailing list