diff --git a/HISTORY b/HISTORY index 2f4feb33..87004f65 100644 --- a/HISTORY +++ b/HISTORY @@ -9130,7 +9130,7 @@ Video Disk Recorder Revision History before including tools.h in case some plugin needs to use the STL and gets error messages regarding one of the template functions defined in tools.h. -2017-06-19: Version 2.3.8 +2017-06-23: Version 2.3.8 - Updated links in the INSTALL file (thanks to Chris Mayo). - Fixed detecting whether a CAM replies to queries, which didn't work on some systems @@ -9138,3 +9138,4 @@ Video Disk Recorder Revision History - Added some missing locks when calling functions from cStatus or cSkin*, and added some text to status.h and skins.h, explaining the locking situation when such functions are called. +- Fixed a possible crash in cStateLockLog. diff --git a/thread.c b/thread.c index 27536791..5ab5f615 100644 --- a/thread.c +++ b/thread.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.c 4.9 2017/06/09 08:27:22 kls Exp $ + * $Id: thread.c 4.10 2017/06/22 15:10:42 kls Exp $ */ #include "thread.h" @@ -558,6 +558,7 @@ cString cBackTrace::GetCaller(int Level, bool Mangled) #ifdef DEBUG_LOCKSEQ #define SLL_SIZE 20 // the number of log entries #define SLL_LENGTH 512 // the maximum length of log entries +#define SLL_THREADS 20 // the maximum number of threads holding locks at the same time (typically well below 10) #define SLL_MAX_LIST 9 // max. number of lists to log #define SLL_WRITE_FLAG 0x80000000 #define SLL_LOCK_FLAG 0x40000000 @@ -569,7 +570,7 @@ private: cVector flags; tThreadId logThreadIds[SLL_SIZE]; int logFlags[SLL_SIZE]; - uint8_t logCounter[SLL_SIZE][SLL_MAX_LIST]; + uint8_t logCounter[SLL_THREADS][SLL_MAX_LIST]; #ifdef DEBUG_LOCKCALL char logCaller[SLL_SIZE][SLL_LENGTH]; #endif @@ -644,15 +645,32 @@ void cStateLockLog::Check(const char *Name, bool Lock, bool Write) int b = 1 << n; cMutexLock MutexLock(&mutex); tThreadId ThreadId = cThread::ThreadId(); - int Index = threadIds.IndexOf(ThreadId); + int Index = -1; + int AvailableIndex = -1; + for (int i = 0; i < threadIds.Size(); i++) { + if (ThreadId == threadIds[i]) { + Index = i; + break; + } + if (threadIds[i] == 0) + AvailableIndex = i; + } if (Index < 0) { - if (Lock) { + if (AvailableIndex < 0) { Index = threadIds.Size(); threadIds.Append(ThreadId); flags.Append(0); } - else - return; + else { + Index = AvailableIndex; + threadIds[Index] = ThreadId; + } + } + if (Index >= SLL_THREADS) { + // should never happen! + esyslog("ERROR: too many threads holding list locks at the same time - stopped logging locks!"); + dumped = true; + return; } bool DoDump = false; if (Lock) { @@ -667,6 +685,8 @@ void cStateLockLog::Check(const char *Name, bool Lock, bool Write) flags[Index] &= ~b; logThreadIds[logIndex] = ThreadId; logFlags[logIndex] = flags[Index] | (Write ? SLL_WRITE_FLAG : 0) | (Lock ? SLL_LOCK_FLAG : 0); + if (flags[Index] == 0) + threadIds[Index] = 0; #ifdef DEBUG_LOCKCALL strn0cpy(logCaller[logIndex], cBackTrace::GetCaller(Lock ? 3 : 5, true), SLL_LENGTH); #endif