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) |
830 | 830 | MythTimer sr_timer; |
831 | 831 | sr_timer.start(); |
832 | 832 | |
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); |
834 | 842 | |
835 | 843 | int sr_elapsed = sr_timer.elapsed(); |
836 | 844 | uint64_t bps = !sr_elapsed ? 1000000001 : |
… |
… |
void RingBuffer::run(void) |
838 | 846 | (double)sr_elapsed); |
839 | 847 | LOG(VB_FILE, LOG_INFO, LOC + |
840 | 848 | 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) |
842 | 850 | .arg(sr_elapsed) |
843 | 851 | .arg(QString("(%1Mbps)").arg((double)bps / 1000000.0))); |
844 | 852 | UpdateStorageRate(bps); |
845 | | rbwlock.unlock(); |
846 | 853 | } |
847 | 854 | |
848 | 855 | if (read_return >= 0) |