[alsa-devel] Deadlock over semaphore issue with aplay while using dmix
Takashi Iwai
tiwai at suse.de
Fri Apr 5 17:27:52 CEST 2013
At Fri, 05 Apr 2013 17:19:52 +0200,
Jaroslav Kysela wrote:
>
> Date 4.4.2013 18:30, Takashi Iwai wrote:
> > At Thu, 04 Apr 2013 13:33:08 +0200,
> > Jaroslav Kysela wrote:
> >>
> >> Date 4.4.2013 11:27, mateen wrote:
> >>> Hi,
> >>>
> >>> I seeing sometimes deadlock issue with dmix when I press CTRL+C.
> >>>
> >>> Aplay's signal handler calls snd_pcm_close() if an interrupt occurs.
> >>> snd_pcm_close() will internally call pcm->ops->close() which will fall to
> >>> snd_pcm_dmix_close() in case you are using dmix.
> >>>
> >>> snd_pcm_dmix_close() will try to acquire the semaphore with
> >>> snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT).
> >>> The same semaphore is acquired in snd_pcm_dmix_sync_area() with
> >>> dmix_down_sem() in case of non-concurrent access.
> >>>
> >>> If semaphore is acquired in snd_pcm_dmix_sync_area() which is in thread
> >>> context and interrupt comes, which invokes the signal handler which is in
> >>> ISR context, which calls snd_pcm_close() which in turn calls
> >>> snd_pcm_dmix_close() then we see a deadlock since semaphore is not released
> >>> from thread context and ISR is waiting indefinitely on the same semaphore.
> >>>
> >>> Please suggest a suitable solution for this.
> >>
> >> It seems that also other configurations (alsa-lib plugins) have trouble
> >> with the closing from the signal handler - I hit mutex issues with the
> >> PulseAudio plugin, too.
> >>
> >> The question is, how we can do a clean path in this case. Looking to the
> >> current alsa-lib code, I would suggest to add the snd_pcm_abort()
> >> function (may be called from the interrupt handler) to notify the
> >> library to not ignore -EINTR return codes from poll() and other i/o ops
> >> and pass it to the caller (application) to finish the normal close sequence.
> >>
> >> Opinions?
> >
> > Isn't it only about the direct plugins with the case where no coherent
> > memory is available? If so, we may just avoid the deadlock by
> > checking some internal flag like the patch below (untested)?
> > It's no perfect but just some proof, of course.
>
> It does not seem like a clean solution. It's just a workaround. I see
> similar locking problems inside the PulseAudio plugin (client library)
> when it's closed from the interrupt handler.
OK, that needs a fix. But, the fix is anyway done to the plugin code
itself, so the necessary change would be pretty similar, I guess.
> Also, looking to apps, the
> best way is to handle the graceful shutdown outside the interrupt
> handler and remove whole "extra" code from the interrupt handler like
> the file header fixups (arecord) from it.
Yeah, agreed. I would suggest to rewrite the code at first.
But this won't "fix" the existing code doing that. It's a bad code,
but resulting in a silent deadlock just due to snd_pcm_close() doesn't
sound good, either.
> The "atomic" notification, that alsa-lib should abort all i/o wait
> operations, is a straigh way to do it. Again, syscalls returns EINTR,
> so we can detect this case and return to the app immediatelly.
The abort state handling itself looks useful.
thanks,
Takashi
>
> Jaroslav
>
> >
> >
> > Takashi
> >
> > ---
> > diff --git a/src/pcm/pcm_direct.h b/src/pcm/pcm_direct.h
> > index 1c35dcb..0ad1475 100644
> > --- a/src/pcm/pcm_direct.h
> > +++ b/src/pcm/pcm_direct.h
> > @@ -123,6 +123,7 @@ struct snd_pcm_direct {
> > int ipc_gid; /* IPC socket gid */
> > int semid; /* IPC global semaphore identification */
> > int shmid; /* IPC global shared memory identification */
> > + int locked;
> > snd_pcm_direct_share_t *shmptr; /* pointer to shared memory area */
> > snd_pcm_t *spcm; /* slave PCM handle */
> > snd_pcm_uframes_t appl_ptr;
> > diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c
> > index 16dba14..1b9aa6a 100644
> > --- a/src/pcm/pcm_dmix.c
> > +++ b/src/pcm/pcm_dmix.c
> > @@ -293,8 +293,17 @@ static void remix_areas(snd_pcm_direct_t *dmix,
> > */
> > #ifndef DOC_HIDDEN
> > #ifdef NO_CONCURRENT_ACCESS
> > -#define dmix_down_sem(dmix) snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT)
> > -#define dmix_up_sem(dmix) snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT)
> > +static void dmix_down_sem(snd_pcm_direct_t *dmix)
> > +{
> > + if (!dmix->locked++)
> > + snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
> > +}
> > +
> > +static void dmix_up_sem(snd_pcm_direct_t *dmix)
> > +{
> > + if (!--dmix->locked)
> > + snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
> > +}
> > #else
> > #define dmix_down_sem(dmix)
> > #define dmix_up_sem(dmix)
> > @@ -772,7 +781,8 @@ static int snd_pcm_dmix_close(snd_pcm_t *pcm)
> >
> > if (dmix->timer)
> > snd_timer_close(dmix->timer);
> > - snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
> > + if (!dmix->locked)
> > + snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT);
> > snd_pcm_close(dmix->spcm);
> > if (dmix->server)
> > snd_pcm_direct_server_discard(dmix);
> >
>
>
> --
> Jaroslav Kysela <perex at perex.cz>
> Linux Kernel Sound Maintainer
> ALSA Project; Red Hat, Inc.
>
More information about the Alsa-devel
mailing list