diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2018-01-28 11:21:28 +0100 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2018-01-28 11:21:28 +0100 |
commit | 0055eeeeb8df2b4e0c6f90338529200a0b3dfa22 (patch) | |
tree | 57c45496d2afe5c0ebb6ab5c6c43a69b97ae1e80 /ci.c | |
parent | 5443fd42195fcc3099325caa3ee189eb64727699 (diff) | |
download | vdr-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.c | 31 |
1 files changed, 30 insertions, 1 deletions
@@ -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)) { |