From 50e09d1232c8d01a8a3f570aa8b3044f8d46a2e6 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 18 Feb 2012 11:22:01 +0100 Subject: [PATCH] Fixed a possible deadlock in time shift mode --- HISTORY | 3 ++- dvbplayer.c | 39 +++++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/HISTORY b/HISTORY index 725450fd..82c02128 100644 --- a/HISTORY +++ b/HISTORY @@ -6847,7 +6847,7 @@ Video Disk Recorder Revision History - Fixed cRecordings::DelByName() to avoid compilation errors with gcc 4.4 (backport from version 1.7.9, thanks to Ralf Schueler). -2012-02-17: Version 1.7.24 +2012-02-18: Version 1.7.24 - Updated the Italian OSD texts (thanks to Diego Pierotto). - Fixed a high load in case a transponder can't be received. @@ -6885,3 +6885,4 @@ Video Disk Recorder Revision History instead of looping through adapter/frontend numbers. This allows for "holes" in the device numbering. - cReadDir::Next() now skips directory entries "." and "..". +- Fixed a possible deadlock in time shift mode. diff --git a/dvbplayer.c b/dvbplayer.c index 017df6d4..d644e203 100644 --- a/dvbplayer.c +++ b/dvbplayer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbplayer.c 2.21 2010/03/07 14:24:26 kls Exp $ + * $Id: dvbplayer.c 2.22 2012/02/17 15:36:41 kls Exp $ */ #include "dvbplayer.h" @@ -87,6 +87,7 @@ class cNonBlockingFileReader : public cThread { private: cUnbufferedFile *f; uchar *buffer; + uchar *result; int wanted; int length; cCondWait newSet; @@ -100,7 +101,7 @@ public: void Clear(void); void Request(cUnbufferedFile *File, int Length); int Result(uchar **Buffer); - bool Reading(void) { return buffer; } + bool Reading(void) { return result; } bool WaitForDataMs(int msToWait); }; @@ -109,6 +110,7 @@ cNonBlockingFileReader::cNonBlockingFileReader(void) { f = NULL; buffer = NULL; + result = NULL; wanted = length = 0; Start(); } @@ -118,6 +120,7 @@ cNonBlockingFileReader::~cNonBlockingFileReader() newSet.Signal(); Cancel(3); free(buffer); + free(result); } void cNonBlockingFileReader::Clear(void) @@ -126,6 +129,8 @@ void cNonBlockingFileReader::Clear(void) f = NULL; free(buffer); buffer = NULL; + free(result); + result = NULL; wanted = length = 0; Unlock(); } @@ -137,18 +142,18 @@ void cNonBlockingFileReader::Request(cUnbufferedFile *File, int Length) wanted = Length; buffer = MALLOC(uchar, wanted); f = File; - Unlock(); newSet.Signal(); + Unlock(); } int cNonBlockingFileReader::Result(uchar **Buffer) { LOCK_THREAD; - if (buffer && length == wanted) { - *Buffer = buffer; - buffer = NULL; + if (result && length == wanted) { + *Buffer = result; + result = NULL; return wanted; - } + } errno = EAGAIN; return -1; } @@ -172,6 +177,8 @@ void cNonBlockingFileReader::Action(void) length = wanted = r; // this will forward the error status to the caller } if (length == wanted) { + result = buffer; + buffer = NULL; cMutexLock NewDataLock(&newDataMutex); newDataCond.Broadcast(); } @@ -183,9 +190,9 @@ void cNonBlockingFileReader::Action(void) bool cNonBlockingFileReader::WaitForDataMs(int msToWait) { - cMutexLock NewDataLock(&newDataMutex); - if (buffer && length == wanted) + if (result && length == wanted) return true; + cMutexLock NewDataLock(&newDataMutex); return newDataCond.TimedWait(newDataMutex, msToWait); } @@ -402,13 +409,13 @@ void cDvbPlayer::Action(void) while (Running()) { if (WaitingForData) - nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data + nonBlockingFileReader->WaitForDataMs(10); // this keeps the CPU load low, but reacts immediately on new data else if (Sleep) { cPoller Poller; DevicePoll(Poller, 10); Sleep = false; if (playMode == pmStill || playMode==pmPause) - cCondWait::SleepMs(3); + cCondWait::SleepMs(10); } { LOCK_THREAD; @@ -470,7 +477,15 @@ void cDvbPlayer::Action(void) } if (!eof) { uchar *b = NULL; - int r = nonBlockingFileReader->Result(&b); + int Retries = 5; + int r; + while (true) { + r = nonBlockingFileReader->Result(&b); + if (r == -1 && errno == EAGAIN && --Retries) + nonBlockingFileReader->WaitForDataMs(10); + else + break; + } if (r > 0) { WaitingForData = false; uint32_t Pts = 0;