Skip to content

Commit

Permalink
DVDRingBuffer: Unlock the ring buffer when waiting on state changes.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Mark Kendall committed May 18, 2011
1 parent 17876e6 commit fd5e33a
Showing 1 changed file with 12 additions and 0 deletions.
12 changes: 12 additions & 0 deletions mythtv/libs/libmythtv/dvdringbuffer.cpp
Expand Up @@ -502,7 +502,12 @@ void DVDRingBuffer::WaitForPlayer(void)
m_playerWait = true;
int count = 0;
while (m_playerWait && count++ < 200)
{
rwlock.unlock();
usleep(10000);
rwlock.lockForWrite();
}

if (m_playerWait)
{
VERBOSE(VB_IMPORTANT, LOC_ERR +
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
usleep(10000);
rwlock.lockForWrite();

// when scanning the file or exiting playback, skip immediately
// otherwise update the timeout in the player
Expand Down Expand Up @@ -919,7 +929,9 @@ int DVDRingBuffer::safe_read(void *data, uint sz)
else
{
m_dvdWaiting = true;
rwlock.unlock();
usleep(10000);
rwlock.lockForWrite();
}

// release buffer
Expand Down

0 comments on commit fd5e33a

Please sign in to comment.