[alsa-devel] EBADFD caused by commit dec428c352217010e4b8bd750d302b8062339d32

Lars Lindqvist lars.lindqvist at yandex.ru
Tue Apr 12 16:52:28 CEST 2016


Den 2016-04-12 skrev Takashi Iwai:
> On Mon, 11 Apr 2016 17:08:01 +0200,
> Lars Lindqvist wrote:
> > 
> > On 2016-04-11 Takashi Iwai wrote:
> > > [Added Qing Cai to Cc, who was the author of the patch in question]
> > > 
> > > On Sun, 10 Apr 2016 23:57:11 +0200,
> > > Lars Lindqvist wrote:
> > > > 
> > > > Hi!
> > > > 
> > > > Since alsa-lib commit  dec428c352217010e4b8bd750d302b8062339d32, I've
> > > > occationally been hit by an EBADFD whenever any program tries to play
> > > > sound.  The  situation  I get is  that the  first shmget succeds,  so
> > > > dmix->shmid >= 0, therefore first_instance = 0.
> > > 
> > > I wonder how does this succeed?  It's a leftover shmem?
> > > But then why it contains the garbage...?
> > 
> > I seem to be able to trigger it by having one client open, starting another,
> > and quickly closing the first one.
> 
> One possible case is that the second stream is opened almost at the
> same time as the first stream, and the second stream reaches to the
> point checking SND_PCM_DIRECT_MAGIC before the first one finishes the
> initialization.  Does a hackish patch like below make any difference?

No it doesn't, the magic check succeeds. The situation is that the first
one has been open for "a long time" when I open the second one. So I
would think that initialization has been completed properly. If the
second one opens just as the first closes, it might be that the second
assigns (correctly) first_instance = 0, but by the time it reaches the
"if (first_instance)" check, the first one has closed, and left garbage.

Lars

> diff --git a/src/pcm/pcm_direct.c b/src/pcm/pcm_direct.c
> index 14de734d98eb..d0aa4258004f 100644
> --- a/src/pcm/pcm_direct.c
> +++ b/src/pcm/pcm_direct.c
> @@ -92,6 +92,7 @@ int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix)
>  {
>  	struct shmid_ds buf;
>  	int tmpid, err, first_instance = 0;
> +	int repeat = 0;
>  	
>  retryget:
>  	dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t),
> @@ -136,6 +137,9 @@ retryget:
>  	} else {
>  		if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) {
>  			snd_pcm_direct_shm_discard(dmix);
> +			/* might be racy, let's retry for a few times */
> +			if (++repeat < 10)
> +				goto retryget;
>  			return -EINVAL;
>  		}
>  	}


More information about the Alsa-devel mailing list