From: Joshua Frkuska Date: Fri, 25 Nov 2016 10:13:40 +0000 (+0530) Subject: pcm: direct: Protect from freeing semaphore when already in use X-Git-Tag: v1.1.3~15 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=2dd78251ff0c4009b478574cca7aef2eb05c2279;p=alsa-lib.git pcm: direct: Protect from freeing semaphore when already in use In the case of dshare, dsnoop, and dmix when a device is opened twice and fails the second time, the semaphore is completely discarded. This creates dangling semaphore data. This patch removes the possibility for the semaphore to be destroyed during a typical open failure by first checking if the shared memory can be destroyed or not. If the shared memory cannot be released it means both it and the semaphore are still in use and therefore the semaphore is just released. Signed-off-by: Joshua Frkuska Signed-off-by: Takashi Iwai --- diff --git a/src/pcm/pcm_dmix.c b/src/pcm/pcm_dmix.c index 2714fb93..2fedb1c1 100644 --- a/src/pcm/pcm_dmix.c +++ b/src/pcm/pcm_dmix.c @@ -1154,9 +1154,10 @@ int snd_pcm_dmix_open(snd_pcm_t **pcmp, const char *name, snd_pcm_close(spcm); if (dmix->u.dmix.shmid_sum >= 0) shm_sum_discard(dmix); - if (dmix->shmid >= 0) - snd_pcm_direct_shm_discard(dmix); - if (snd_pcm_direct_semaphore_discard(dmix) < 0) + if ((dmix->shmid >= 0) && (snd_pcm_direct_shm_discard(dmix))) { + if (snd_pcm_direct_semaphore_discard(dmix)) + snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT); + } else snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); _err_nosem: if (dmix) { diff --git a/src/pcm/pcm_dshare.c b/src/pcm/pcm_dshare.c index 9b478a71..01f5eed8 100644 --- a/src/pcm/pcm_dshare.c +++ b/src/pcm/pcm_dshare.c @@ -846,9 +846,10 @@ int snd_pcm_dshare_open(snd_pcm_t **pcmp, const char *name, snd_pcm_direct_client_discard(dshare); if (spcm) snd_pcm_close(spcm); - if (dshare->shmid >= 0) - snd_pcm_direct_shm_discard(dshare); - if (snd_pcm_direct_semaphore_discard(dshare) < 0) + if ((dshare->shmid >= 0) && (snd_pcm_direct_shm_discard(dshare))) { + if (snd_pcm_direct_semaphore_discard(dshare)) + snd_pcm_direct_semaphore_final(dshare, DIRECT_IPC_SEM_CLIENT); + } else snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT); _err_nosem: if (dshare) { diff --git a/src/pcm/pcm_dsnoop.c b/src/pcm/pcm_dsnoop.c index 4efbc53d..1aedf3cb 100644 --- a/src/pcm/pcm_dsnoop.c +++ b/src/pcm/pcm_dsnoop.c @@ -719,10 +719,12 @@ int snd_pcm_dsnoop_open(snd_pcm_t **pcmp, const char *name, snd_pcm_direct_client_discard(dsnoop); if (spcm) snd_pcm_close(spcm); - if (dsnoop->shmid >= 0) - snd_pcm_direct_shm_discard(dsnoop); - if (snd_pcm_direct_semaphore_discard(dsnoop) < 0) + if ((dsnoop->shmid >= 0) && (snd_pcm_direct_shm_discard(dsnoop))) { + if (snd_pcm_direct_semaphore_discard(dsnoop)) + snd_pcm_direct_semaphore_final(dsnoop, DIRECT_IPC_SEM_CLIENT); + } else snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT); + _err_nosem: if (dsnoop) { free(dsnoop->bindings);