| diff -aruN alsa-lib-1.0.27.2/src/pcm/pcm_direct.c alsa-lib-1.0.27.2.N/src/pcm/pcm_direct.c |
| --- alsa-lib-1.0.27.2/src/pcm/pcm_direct.c 2013-07-08 05:31:36.000000000 -0700 |
| +++ alsa-lib-1.0.27.2.N/src/pcm/pcm_direct.c 2017-07-13 13:18:48.424261391 -0700 |
| @@ -91,13 +91,20 @@ |
| int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix) |
| { |
| struct shmid_ds buf; |
| - int tmpid, err; |
| + int tmpid, err, first_instance = 0; |
| |
| retryget: |
| dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t), |
| - IPC_CREAT | dmix->ipc_perm); |
| + dmix->ipc_perm); |
| + if (dmix->shmid < 0 && errno == ENOENT) { |
| + if ((dmix->shmid = shmget(dmix->ipc_key, sizeof(snd_pcm_direct_share_t), |
| + IPC_CREAT | IPC_EXCL | dmix->ipc_perm)) != -1) |
| + first_instance = 1; |
| + else if (errno == EEXIST) |
| + goto retryget; |
| + } |
| err = -errno; |
| - if (dmix->shmid < 0){ |
| + if (dmix->shmid < 0) { |
| if (errno == EINVAL) |
| if ((tmpid = shmget(dmix->ipc_key, 0, dmix->ipc_perm)) != -1) |
| if (!shmctl(tmpid, IPC_STAT, &buf)) |
| @@ -119,7 +126,7 @@ |
| snd_pcm_direct_shm_discard(dmix); |
| return err; |
| } |
| - if (buf.shm_nattch == 1) { /* we're the first user, clear the segment */ |
| + if (first_instance) { /* we're the first user, clear the segment */ |
| memset(dmix->shmptr, 0, sizeof(snd_pcm_direct_share_t)); |
| if (dmix->ipc_gid >= 0) { |
| buf.shm_perm.gid = dmix->ipc_gid; |
| @@ -130,6 +137,7 @@ |
| } else { |
| if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) { |
| snd_pcm_direct_shm_discard(dmix); |
| + SNDERR("Error in second instance"); |
| return -EINVAL; |
| } |
| } |
| diff -aruN alsa-lib-1.0.27.2/src/pcm/pcm_dmix.c alsa-lib-1.0.27.2.N/src/pcm/pcm_dmix.c |
| --- alsa-lib-1.0.27.2/src/pcm/pcm_dmix.c 2013-07-08 05:31:36.000000000 -0700 |
| +++ alsa-lib-1.0.27.2.N/src/pcm/pcm_dmix.c 2017-07-13 13:15:33.874553985 -0700 |
| @@ -1013,6 +1013,7 @@ |
| dmix->max_periods = opts->max_periods; |
| dmix->sync_ptr = snd_pcm_dmix_sync_ptr; |
| |
| + retry: |
| if (first_instance) { |
| /* recursion is already checked in |
| snd_pcm_direct_get_slave_ipc_offset() */ |
| @@ -1069,6 +1070,13 @@ |
| SND_PCM_APPEND, |
| NULL); |
| if (ret < 0) { |
| + /* all other streams have been closed; |
| + * retry as the first instance |
| + */ |
| + if (ret == -EBADFD) { |
| + first_instance = 1; |
| + goto retry; |
| + } |
| SNDERR("unable to open slave"); |
| goto _err; |
| } |