diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 6a8db43a..eda44d39 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3673,6 +3673,7 @@ Helmut Binder for fixing handling incomplete multi-packet CAT for fixing a memory leak in handling the NIT for reporting a possible memory leak in creating fonts + for fixing a possible deadlock in cDevice::DetachAllReceivers() Ulrich Eckhardt for reporting a problem with shutdown after user inactivity in case a plugin is diff --git a/HISTORY b/HISTORY index bb560344..99158f26 100644 --- a/HISTORY +++ b/HISTORY @@ -9775,3 +9775,4 @@ Video Disk Recorder Revision History - Added some missing "AUTO" values to vdr.5 (thanks to Winfried Köhler). - Fixed handling zero bytes in cH264Parser (thanks to Christoph Haubrich). - Fixed handling error conditions in the index file (reported by Markus Ehrnsperger). +- Fixed a possible deadlock in cDevice::DetachAllReceivers() (thanks to Helmut Binder). diff --git a/device.c b/device.c index fb251cd1..4b9c9cc7 100644 --- a/device.c +++ b/device.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 5.4 2022/01/13 10:56:01 kls Exp $ + * $Id: device.c 5.5 2022/01/24 16:53:45 kls Exp $ */ #include "device.h" @@ -437,6 +437,12 @@ cDevice *cDevice::GetDeviceForTransponder(const cChannel *Channel, int Priority) return Device; } +void cDevice::ReleaseCamSlot(void) +{ + if (camSlot && !camSlot->IsDecrypting() && !camSlot->IsActivating()) + camSlot->Assign(NULL); +} + bool cDevice::HasCi(void) { return false; @@ -1823,7 +1829,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver) return false; } -void cDevice::Detach(cReceiver *Receiver) +void cDevice::Detach(cReceiver *Receiver, bool ReleaseCam) { if (!Receiver || Receiver->device != this) return; @@ -1845,8 +1851,8 @@ void cDevice::Detach(cReceiver *Receiver) if (camSlot) { if (Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver camSlot->StartDecrypting(); - if (!camSlot->IsDecrypting() && !camSlot->IsActivating()) - camSlot->Assign(NULL); + if (ReleaseCam) + ReleaseCamSlot(); } } if (!receiversLeft) @@ -1860,8 +1866,9 @@ void cDevice::DetachAll(int Pid) for (int i = 0; i < MAXRECEIVERS; i++) { cReceiver *Receiver = receiver[i]; if (Receiver && Receiver->WantsPid(Pid)) - Detach(Receiver); + Detach(Receiver, false); } + ReleaseCamSlot(); } } @@ -1869,7 +1876,8 @@ void cDevice::DetachAllReceivers(void) { cMutexLock MutexLock(&mutexReceiver); for (int i = 0; i < MAXRECEIVERS; i++) - Detach(receiver[i]); + Detach(receiver[i], false); + ReleaseCamSlot(); } // --- cTSBuffer ------------------------------------------------------------- diff --git a/device.h b/device.h index 63eef603..2d0ac12f 100644 --- a/device.h +++ b/device.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 5.1 2021/05/21 12:51:16 kls Exp $ + * $Id: device.h 5.2 2022/01/24 16:53:45 kls Exp $ */ #ifndef __DEVICE_H @@ -465,6 +465,8 @@ public: private: cCamSlot *camSlot; + void ReleaseCamSlot(void); + ///< Releases the CAM slot if it is currently not used. public: virtual bool HasCi(void); ///< Returns true if this device has a Common Interface. @@ -852,8 +854,11 @@ public: ///< Returns true if we are currently receiving. The parameter has no meaning (for backwards compatibility only). bool AttachReceiver(cReceiver *Receiver); ///< Attaches the given receiver to this device. - void Detach(cReceiver *Receiver); + void Detach(cReceiver *Receiver, bool ReleaseCam = true); ///< Detaches the given receiver from this device. + ///< If ReleaseCam is true, the CAM slot will be released if it + ///< is no longer used. Otherwise the caller must call ReleaseCamSlot() after + ///< calling this function. void DetachAll(int Pid); ///< Detaches all receivers from this device for this pid. virtual void DetachAllReceivers(void);