diff mbox series

[2/3] pcm_ioplug: Don't unlock+lock if we're not locked

Message ID 20190922032853.6123-3-thematrixeatsyou@gmail.com (mailing list archive)
State New, archived
Headers show
Series Make pcm_ioplug check lock status before locking (fixes pcm_jack lockups) | expand

Commit Message

Ben Russell Sept. 22, 2019, 3:28 a.m. UTC
This fixes a deadlock when using the pcm_jack plugin via a plug.

Some snd_pcm_ioplug_* functions assumed that they were being
called with the pcm mutex locked, and would perform an
unlock-act-lock sequence in order to allow the relevant function to
lock the mutex itself.

If the mutex was not locked before calling these functions, it
would silently fail on unlocking the mutex, and then erroneously
leave the mutex locked as it left the function.

This patch checks to see if the mutex is locked before attempting
the unlock-act-lock sequence. If the mutex is not locked when
entering these functions, then we act and leave the mutex unlocked.

Signed-off-by: Ben Russell <thematrixeatsyou@gmail.com>
---
 src/pcm/pcm_ioplug.c | 50 +++++++++++++++++++++++++++++++-------------
 1 file changed, 35 insertions(+), 15 deletions(-)
diff mbox series

Patch

diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c
index a437ca32..a94ecd96 100644
--- a/src/pcm/pcm_ioplug.c
+++ b/src/pcm/pcm_ioplug.c
@@ -164,9 +164,13 @@  static int snd_pcm_ioplug_prepare(snd_pcm_t *pcm)
 
 	snd_pcm_ioplug_reset(pcm);
 	if (io->data->callback->prepare) {
-		snd_pcm_unlock(pcm); /* to avoid deadlock */
-		err = io->data->callback->prepare(io->data);
-		snd_pcm_lock(pcm);
+		if (snd_pcm_is_locked(pcm)) {
+			snd_pcm_unlock(pcm); /* to avoid deadlock */
+			err = io->data->callback->prepare(io->data);
+			snd_pcm_lock(pcm);
+		} else {
+			err = io->data->callback->prepare(io->data);
+		}
 	}
 	if (err < 0)
 		return err;
@@ -463,9 +467,13 @@  static int snd_pcm_ioplug_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params)
 	if (!io->data->callback->sw_params)
 		return 0;
 
-	snd_pcm_unlock(pcm); /* to avoid deadlock */
-	err = io->data->callback->sw_params(io->data, params);
-	snd_pcm_lock(pcm);
+	if (snd_pcm_is_locked(pcm)) {
+		snd_pcm_unlock(pcm); /* to avoid deadlock */
+		err = io->data->callback->sw_params(io->data, params);
+		snd_pcm_lock(pcm);
+	} else {
+		err = io->data->callback->sw_params(io->data, params);
+	}
 
 	return err;
 }
@@ -764,9 +772,13 @@  static int snd_pcm_ioplug_poll_descriptors_count(snd_pcm_t *pcm)
 	int err = 1;
 
 	if (io->data->callback->poll_descriptors_count) {
-		snd_pcm_unlock(pcm); /* to avoid deadlock */
-		err = io->data->callback->poll_descriptors_count(io->data);
-		snd_pcm_lock(pcm);
+		if (snd_pcm_is_locked(pcm)) {
+			snd_pcm_unlock(pcm); /* to avoid deadlock */
+			err = io->data->callback->poll_descriptors_count(io->data);
+			snd_pcm_lock(pcm);
+		} else {
+			err = io->data->callback->poll_descriptors_count(io->data);
+		}
 	}
 	return err;
 }
@@ -777,9 +789,13 @@  static int snd_pcm_ioplug_poll_descriptors(snd_pcm_t *pcm, struct pollfd *pfds,
 	int err;
 
 	if (io->data->callback->poll_descriptors) {
-		snd_pcm_unlock(pcm); /* to avoid deadlock */
-		err = io->data->callback->poll_descriptors(io->data, pfds, space);
-		snd_pcm_lock(pcm);
+		if (snd_pcm_is_locked(pcm)) {
+			snd_pcm_unlock(pcm); /* to avoid deadlock */
+			err = io->data->callback->poll_descriptors(io->data, pfds, space);
+			snd_pcm_lock(pcm);
+		} else {
+			err = io->data->callback->poll_descriptors(io->data, pfds, space);
+		}
 		return err;
 	}
 	if (pcm->poll_fd < 0)
@@ -799,9 +815,13 @@  static int snd_pcm_ioplug_poll_revents(snd_pcm_t *pcm, struct pollfd *pfds, unsi
 	int err;
 
 	if (io->data->callback->poll_revents) {
-		snd_pcm_unlock(pcm); /* to avoid deadlock */
-		err = io->data->callback->poll_revents(io->data, pfds, nfds, revents);
-		snd_pcm_lock(pcm);
+		if (snd_pcm_is_locked(pcm)) {
+			snd_pcm_unlock(pcm); /* to avoid deadlock */
+			err = io->data->callback->poll_revents(io->data, pfds, nfds, revents);
+			snd_pcm_lock(pcm);
+		} else {
+			err = io->data->callback->poll_revents(io->data, pfds, nfds, revents);
+		}
 	} else {
 		*revents = pfds->revents;
 		err = 0;