From: Shengjiu Wang Date: Fri, 12 Jun 2015 08:15:08 +0000 (+0800) Subject: PCM: snd_pcm_xxxx_drain() maybe blocked after suspend and resume X-Git-Tag: v1.1.0~67 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=9ee6ec80b80268932a372522ca192168e7812ccf;p=alsa-lib.git PCM: snd_pcm_xxxx_drain() maybe blocked after suspend and resume After suspend and resume, the alsa driver is stopped. But if alsa-lib run into snd_pcm_xxxx_drain(), it need to wait avail >= pcm->stop_threshold, otherwise, it will not exit the loop, so finally it is blocked at poll() of snd_pcm_wait_nocheck(pcm, -1). This patch is to add state check after snd_pcm_wait_nocheck(pcm, -1), if the state is SND_PCM_STATE_SUSPENDED, then return error. Signed-off-by: Shengjiu Wang Signed-off-by: Takashi Iwai --- diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index 4acbaf0e..58e4975d 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -617,6 +617,13 @@ static int snd_pcm_dmix_drain(snd_pcm_t *pcm) snd_pcm_uframes_t stop_threshold; int err; + switch (snd_pcm_state(dmix->spcm)) { + case SND_PCM_STATE_SUSPENDED: + return -ESTRPIPE; + default: + break; + } + if (dmix->state == SND_PCM_STATE_OPEN) return -EBADFD; if (pcm->mode & SND_PCM_NONBLOCK) @@ -649,6 +656,13 @@ static int snd_pcm_dmix_drain(snd_pcm_t *pcm) snd_pcm_dmix_sync_area(pcm); snd_pcm_wait_nocheck(pcm, -1); snd_pcm_direct_clear_timer_queue(dmix); /* force poll to wait */ + + switch (snd_pcm_state(dmix->spcm)) { + case SND_PCM_STATE_SUSPENDED: + return -ESTRPIPE; + default: + break; + } } } while (dmix->state == SND_PCM_STATE_DRAINING); pcm->stop_threshold = stop_threshold; diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index b51758fb..02370dc7 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -368,6 +368,13 @@ static int snd_pcm_dshare_drain(snd_pcm_t *pcm) snd_pcm_uframes_t stop_threshold; int err; + switch (snd_pcm_state(dshare->spcm)) { + case SND_PCM_STATE_SUSPENDED: + return -ESTRPIPE; + default: + break; + } + if (dshare->state == SND_PCM_STATE_OPEN) return -EBADFD; if (pcm->mode & SND_PCM_NONBLOCK) @@ -400,6 +407,13 @@ static int snd_pcm_dshare_drain(snd_pcm_t *pcm) snd_pcm_dshare_sync_area(pcm); snd_pcm_wait_nocheck(pcm, -1); snd_pcm_direct_clear_timer_queue(dshare); /* force poll to wait */ + + switch (snd_pcm_state(dshare->spcm)) { + case SND_PCM_STATE_SUSPENDED: + return -ESTRPIPE; + default: + break; + } } } while (dshare->state == SND_PCM_STATE_DRAINING); pcm->stop_threshold = stop_threshold;