diff options
authorMark Kendall <>2011-05-18 15:41:49 (GMT)
committer Mark Kendall <>2011-05-18 15:41:49 (GMT)
commitfd5e33a69b630aa9c0b94a8c2dd7693f02726316 (patch)
parent17876e6a3402c071fd572a026156ca6c77a3ca1d (diff)
DVDRingBuffer: Unlock the ring buffer when waiting on state changes.
The DVD ringbuffer does not use the read ahead thread and hence holding the writelock during safe_read is not strictly necessary (see RingBuffer::ReadPriv). DVDRingBuffer::safe_read can also hold that lock for tens of seconds when, for example, displaying a still frame (the dvd device simply returns specific events, but not data, until it is told to skip the still frame). Under normal operation this is not a problem but events received from external sources (such as network control) can trigger code that tries to lock the ringbuffer from the main UI thread (e.g. RingBuffer::GetFilename). The lock is not obtained, event processing in the main thread is blocked and the wait state in the ringbuffer thread is not cleared - and the frontend deadlocks as a result. The solution is to release the lock while sleeping within DVDRingBuffer::safe_read to allow other threads to obtain the lock temporarily. I've also added a warning message should the read ahead thread be running in the DVD ringbuffer. Refs #9780
1 files changed, 12 insertions, 0 deletions
diff --git a/mythtv/libs/libmythtv/dvdringbuffer.cpp b/mythtv/libs/libmythtv/dvdringbuffer.cpp
index 617fac4..4025e7c 100644
--- a/mythtv/libs/libmythtv/dvdringbuffer.cpp
+++ b/mythtv/libs/libmythtv/dvdringbuffer.cpp
@@ -502,7 +502,12 @@ void DVDRingBuffer::WaitForPlayer(void)
m_playerWait = true;
int count = 0;
while (m_playerWait && count++ < 200)
+ {
+ rwlock.unlock();
+ rwlock.lockForWrite();
+ }
if (m_playerWait)
@@ -530,6 +535,9 @@ int DVDRingBuffer::safe_read(void *data, uint sz)
return -1;
+ if (readaheadrunning)
+ VERBOSE(VB_IMPORTANT, LOC_ERR + "read ahead thread running.");
while (needed)
blockBuf = m_dvdBlockWriteBuf;
@@ -886,7 +894,9 @@ int DVDRingBuffer::safe_read(void *data, uint sz)
// pause a little as the dvdnav VM will continue to return
// this event until it has been skipped
+ rwlock.unlock();
+ rwlock.lockForWrite();
// when scanning the file or exiting playback, skip immediately
// otherwise update the timeout in the player
@@ -919,7 +929,9 @@ int DVDRingBuffer::safe_read(void *data, uint sz)
m_dvdWaiting = true;
+ rwlock.unlock();
+ rwlock.lockForWrite();
// release buffer