Fixed a possible deadlock when quickly zapping through encrypted channels

This commit is contained in:
Klaus Schmidinger 2018-01-28 11:21:28 +01:00
parent 5443fd4219
commit 0055eeeeb8
3 changed files with 34 additions and 2 deletions

View File

@ -2627,6 +2627,7 @@ J
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

View File

@ -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).

31
ci.c
View File

@ -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)) {