summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY3
-rw-r--r--thread.c32
2 files changed, 28 insertions, 7 deletions
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<int> 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