summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS1
-rw-r--r--HISTORY4
-rw-r--r--ci.c31
3 files changed, 34 insertions, 2 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 9a07ecce..07cb746a 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -2627,6 +2627,7 @@ Jörg Wendel <vdr-ml@jwendel.de>
for making cEpgHandlers::BeginSegmentTransfer() boolean
for suggesting to change tEventID back to u_int32_t
for adding the 'aux' member to cEvent
+ for reporting a possible deadlock when quickly zapping through encrypted channels
Peter Pinnau <vdr@unterbrecher.de>
for reporting that 'uint32_t' requires including stdint.h in font.h on some systems
diff --git a/HISTORY b/HISTORY
index 16d77b9b..0b412acb 100644
--- a/HISTORY
+++ b/HISTORY
@@ -9162,7 +9162,7 @@ Video Disk Recorder Revision History
a subdirectory.
- SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details).
-2018-01-17: Version 2.3.9
+2018-01-28: Version 2.3.9
- Updated the Italian OSD texts (thanks to Diego Pierotto).
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
@@ -9245,3 +9245,5 @@ Video Disk Recorder Revision History
- Now using the 'example' macro in vdr.5 (thanks to Chris Mayo).
- Now unlocking the Recordings list before displaying an error message in
cMenuPathEdit::ApplyChanges() and cReplayControl::Stop() (reported by Matthias Senzel).
+- Fixed a possible deadlock when quickly zapping through encrypted channels (reported
+ by Jörg Wendel).
diff --git a/ci.c b/ci.c
index b6ea3269..3eb40cb6 100644
--- a/ci.c
+++ b/ci.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: ci.c 4.18 2017/06/19 12:13:38 kls Exp $
+ * $Id: ci.c 4.19 2018/01/28 11:14:40 kls Exp $
*/
#include "ci.h"
@@ -122,6 +122,8 @@ private:
uchar *bufp;
uchar mtdCatBuffer[TS_SIZE]; // TODO: handle multi packet CATs!
int length;
+ cMutex mutex;
+ bool handlingPid;
void AddEmmPid(int Pid);
void DelEmmPids(void);
public:
@@ -130,6 +132,15 @@ public:
virtual void Receive(const uchar *Data, int Length);
bool HasCaPids(void) const { return NumPids() - emmPids.Size() - 1 > 0; }
void Reset(void) { DelEmmPids(); catVersion = -1; }
+ bool HandlingPid(void);
+ ///< The cCaPidReceiver adds/deletes PIDs to/from the base class cReceiver,
+ ///< which in turn does the same on the cDevice it is attached to. The cDevice
+ ///< then sets the PIDs on the assigned cCamSlot, which can cause a deadlock on the
+ ///< cCamSlot's mutex if a cReceiver is detached from the device at the same time.
+ ///< Since these PIDs, however, are none that have to be decrypted,
+ ///< it is not necessary to set them in the CAM. Therefore this function is
+ ///< used in cCamSlot::SetPid() to detect this situation, and thus avoid the
+ ///< deadlock.
};
cCaPidReceiver::cCaPidReceiver(void)
@@ -137,7 +148,11 @@ cCaPidReceiver::cCaPidReceiver(void)
catVersion = -1;
bufp = NULL;
length = 0;
+ handlingPid = false;
+ cMutexLock MutexLock(&mutex);
+ handlingPid = true;
AddPid(CATPID);
+ handlingPid = false;
}
void cCaPidReceiver::AddEmmPid(int Pid)
@@ -147,14 +162,20 @@ void cCaPidReceiver::AddEmmPid(int Pid)
return;
}
emmPids.Append(Pid);
+ cMutexLock MutexLock(&mutex);
+ handlingPid = true;
AddPid(Pid);
+ handlingPid = false;
}
void cCaPidReceiver::DelEmmPids(void)
{
+ cMutexLock MutexLock(&mutex);
+ handlingPid = true;
for (int i = 0; i < emmPids.Size(); i++)
DelPid(emmPids[i]);
emmPids.Clear();
+ handlingPid = false;
}
void cCaPidReceiver::Receive(const uchar *Data, int Length)
@@ -239,6 +260,12 @@ void cCaPidReceiver::Receive(const uchar *Data, int Length)
}
}
+bool cCaPidReceiver::HandlingPid(void)
+{
+ cMutexLock MutexLock(&mutex);
+ return handlingPid;
+}
+
// --- cCaActivationReceiver -------------------------------------------------
// A receiver that is used to make the device stay on a given channel and
@@ -2588,6 +2615,8 @@ void cCamSlot::AddPid(int ProgramNumber, int Pid, int StreamType)
void cCamSlot::SetPid(int Pid, bool Active)
{
+ if (caPidReceiver && caPidReceiver->HandlingPid())
+ return;
cMutexLock MutexLock(&mutex);
for (cCiCaProgramData *p = caProgramList.First(); p; p = caProgramList.Next(p)) {
for (cCiCaPidData *q = p->pidList.First(); q; q = p->pidList.Next(q)) {