At Sun, 20 May 2012 18:25:30 +0100, Alan Horstmann wrote:
Hi,
Can snd_pcm_drain() be safely called on a non-running stream - particularly one in SND_PCM_STATE_XRUN? I can demonstrate lock-ups (on rather old Alsa versions, though) when _drain is called on a stream in Xrun but it does seem to vary between hardwares.
Hm, that's odd. At least there should be no lock up in the core code. Are you running the recent kernel?
However, the docs at:
http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html
suggest that it should be fine.
The snd_pcm_drop() calls simply ignore streams other than RUNNING, PREPARE and PAUSED. So, it's basically safe.
OTOH, it'd be better to drop XRUN streams to SETUP after this call, and there should be sane state checks at the beginning. I committed the patch below to my tree now.
Takashi
--- From: Takashi Iwai tiwai@suse.de Subject: [PATCH] ALSA: pcm - Add proper state checks to snd_pcm_drain()
The handling for some PCM states is missing for snd_pcm_drain(). At least, XRUN streams should be simply dropped to SETUP, and a few initial invalid states should be rejected.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/pcm_native.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 3fe99e6..53b5ada 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1360,7 +1360,14 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) { - substream->runtime->trigger_master = substream; + struct snd_pcm_runtime *runtime = substream->runtime; + switch (runtime->status->state) { + case SNDRV_PCM_STATE_OPEN: + case SNDRV_PCM_STATE_DISCONNECTED: + case SNDRV_PCM_STATE_SUSPENDED: + return -EBADFD; + } + runtime->trigger_master = substream; return 0; }
@@ -1379,6 +1386,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state) case SNDRV_PCM_STATE_RUNNING: runtime->status->state = SNDRV_PCM_STATE_DRAINING; break; + case SNDRV_PCM_STATE_XRUN: + runtime->status->state = SNDRV_PCM_STATE_SETUP; + break; default: break; }