summaryrefslogtreecommitdiff
path: root/ci.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2018-01-28 11:21:28 +0100
committerKlaus Schmidinger <vdr@tvdr.de>2018-01-28 11:21:28 +0100
commit0055eeeeb8df2b4e0c6f90338529200a0b3dfa22 (patch)
tree57c45496d2afe5c0ebb6ab5c6c43a69b97ae1e80 /ci.c
parent5443fd42195fcc3099325caa3ee189eb64727699 (diff)
downloadvdr-0055eeeeb8df2b4e0c6f90338529200a0b3dfa22.tar.gz
vdr-0055eeeeb8df2b4e0c6f90338529200a0b3dfa22.tar.bz2
Fixed a possible deadlock when quickly zapping through encrypted channels
Diffstat (limited to 'ci.c')
-rw-r--r--ci.c31
1 files changed, 30 insertions, 1 deletions
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)) {