53d00fffc2
https://github.com/pulseaudio/pulseaudio/blob/master/src/pulsecore/mutex-posix.c#L55
https://github.com/pulseaudio/pulseaudio/blob/master/src/pulse/thread-mainloop.c#L118
413a8f8917
pulseaudio uses a prio-inheriting mutex since the above revision
that is paised with a condition variable; the behavior of this
was broken in musl until the above patches, which would result
in pulseaudio deadlocking with gstreamer pulsesink (most often
with webkit) and possibly other things.
Fixes https://github.com/void-linux/void-packages/issues/15631
56 lines
2.2 KiB
Diff
56 lines
2.2 KiB
Diff
From 2d0bbe6c788938d1332609c014eeebc1dff966ac Mon Sep 17 00:00:00 2001
|
|
From: Rich Felker <dalias@aerifal.cx>
|
|
Date: Mon, 26 Oct 2020 15:56:25 -0400
|
|
Subject: fix pthread_cond_wait paired with with priority-inheritance mutex
|
|
|
|
pthread_cond_wait arranged for requeued waiters to wake when the mutex
|
|
is unlocked by temporarily adjusting the mutex's waiter count. commit
|
|
54ca677983d47529bab8752315ac1a2b49888870 broke this when introducing
|
|
PI mutexes by repurposing the waiter count field of the mutex
|
|
structure. since then, for PI mutexes, the waiter count adjustment was
|
|
misinterpreted by the mutex locking code as indicating that the mutex
|
|
is non a non-recoverable state.
|
|
|
|
it would be possible to special-case PI mutexes here, but instead just
|
|
drop all adjustment of the waiters count, and instead use the lock
|
|
word waiters bit for all mutex types. since the mutex is either held
|
|
by the caller or in unrecoverable state at the time the bit is set, it
|
|
will necessarily still be set at the time of any subsequent valid
|
|
unlock operation, and this will produce the desired effect of waking
|
|
the next waiter.
|
|
|
|
if waiter counts are entirely dropped at some point in the future this
|
|
code should still work without modification.
|
|
---
|
|
src/thread/pthread_cond_timedwait.c | 11 +++++------
|
|
1 file changed, 5 insertions(+), 6 deletions(-)
|
|
|
|
(limited to 'src/thread/pthread_cond_timedwait.c')
|
|
|
|
diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c
|
|
index d1501240..f5f37af1 100644
|
|
--- a/src/thread/pthread_cond_timedwait.c
|
|
+++ b/src/thread/pthread_cond_timedwait.c
|
|
@@ -146,14 +146,13 @@ relock:
|
|
|
|
if (oldstate == WAITING) goto done;
|
|
|
|
- if (!node.next) a_inc(&m->_m_waiters);
|
|
-
|
|
/* Unlock the barrier that's holding back the next waiter, and
|
|
* either wake it or requeue it to the mutex. */
|
|
- if (node.prev)
|
|
- unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & 128);
|
|
- else
|
|
- a_dec(&m->_m_waiters);
|
|
+ if (node.prev) {
|
|
+ int val = m->_m_lock;
|
|
+ if (val>0) a_cas(&m->_m_lock, val, val|0x80000000);
|
|
+ unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128));
|
|
+ }
|
|
|
|
/* Since a signal was consumed, cancellation is not permitted. */
|
|
if (e == ECANCELED) e = 0;
|
|
--
|
|
cgit v1.2.1
|
|
|