Ticket #9959: 0001-ringbuffer-Fix-a-deadlock-in-readahead.patch

File 0001-ringbuffer-Fix-a-deadlock-in-readahead.patch, 2.3 KB (added by Lawrence Rust <lvr@…>, 10 years ago)
  • mythtv/libs/libmythtv/ringbuffer.cpp

    From 4a23c735c7d0120c0851aa0fb7cf818e1c01d0e6 Mon Sep 17 00:00:00 2001
    From: Lawrence Rust <lvr@softsystem.co.uk>
    Date: Mon, 1 Aug 2011 11:15:20 +0200
    Subject: [PATCH] ringbuffer: Fix a deadlock in readahead
    
    This fixes an error in the lock acquisition heirarchy in run() when it
    calls safe_read().
    
    If an error is encountered in fileringbuffer::safe_read() then poslock
    is read locked prior to calling Seek() but run() has already read locked
    rbwlock which leads to a violation of the lock heirarchy
    rwlock->poslock->rbrlock->rbwlock.
    
    This fix releases rbwlock prior to calling safe_read.
    
    NB this bug also affects fixes/0.24
    
    Signed-off-by: Lawrence Rust <lvr@softsystem.co.uk>
    ---
     mythtv/libs/libmythtv/ringbuffer.cpp |   13 ++++++++++---
     1 files changed, 10 insertions(+), 3 deletions(-)
    
    diff --git a/mythtv/libs/libmythtv/ringbuffer.cpp b/mythtv/libs/libmythtv/ringbuffer.cpp
    index 4c5a587..8893621 100644
    a b void RingBuffer::run(void) 
    830830            MythTimer sr_timer;
    831831            sr_timer.start();
    832832
    833             read_return = safe_read(readAheadBuffer + rbwpos, totfree);
     833            // NB If an error is encountered in FileRingBuffer::safe_read()
     834            // then poslock is read locked prior to calling Seek().
     835            // However, we have rbwlock locked which violates the lock heirarchy:
     836            //  rwlock->poslock->rbrlock->rbwlock
     837            // This can cause a client to deadlock, so release rbwlock.
     838            int rbwposcopy = rbwpos;
     839            rbwlock.unlock();
     840
     841            read_return = safe_read(readAheadBuffer + rbwposcopy, totfree);
    834842
    835843            int sr_elapsed = sr_timer.elapsed();
    836844            uint64_t bps = !sr_elapsed ? 1000000001 :
    void RingBuffer::run(void) 
    838846                                      (double)sr_elapsed);
    839847            LOG(VB_FILE, LOG_INFO, LOC +
    840848                QString("safe_read(...@%1, %2) -> %3, took %4 ms %5")
    841                     .arg(rbwpos).arg(totfree).arg(read_return)
     849                    .arg(rbwposcopy).arg(totfree).arg(read_return)
    842850                    .arg(sr_elapsed)
    843851                    .arg(QString("(%1Mbps)").arg((double)bps / 1000000.0)));
    844852            UpdateStorageRate(bps);
    845             rbwlock.unlock();
    846853        }
    847854
    848855        if (read_return >= 0)