]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
tvh thread: add mutex magic check routines
authorJaroslav Kysela <perex@perex.cz>
Sat, 8 Dec 2018 17:44:31 +0000 (18:44 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sat, 8 Dec 2018 17:44:31 +0000 (18:44 +0100)
src/http.c
src/idnode.c
src/input/mpegts/linuxdvb/linuxdvb_ca.c
src/lang_codes.c
src/spawn.c
src/tvh_locale.c
src/tvh_thread.c
src/tvh_thread.h
src/webui/comet.c

index 13ec1d87dab46e670f038219a43aa7e64f6a5f53..af6521f7572dbbd451ce30b97e1d5ff82af7f809 100644 (file)
@@ -33,7 +33,7 @@
 void *http_server;
 static int http_server_running;
 
-static tvh_mutex_t http_paths_mutex = { .mutex = PTHREAD_MUTEX_INITIALIZER };
+static tvh_mutex_t http_paths_mutex = TVH_THREAD_MUTEX_INITIALIZER;
 static http_path_list_t http_paths;
 
 static struct strtab HTTP_cmdtab[] = {
index 29e4508c1585cc2c91ce40b42eb75e514acbd1bc..2e903d68f7131d84593f76f25e2a16595f353a31 100644 (file)
@@ -52,7 +52,7 @@ static pthread_t  save_tid;
 static int        save_running;
 static mtimer_t   save_timer;
 
-static tvh_mutex_t idnode_lnotify_mutex = { .mutex = PTHREAD_MUTEX_INITIALIZER };
+static tvh_mutex_t idnode_lnotify_mutex = TVH_THREAD_MUTEX_INITIALIZER;
 static tvh_uuid_set_t  idnode_lnotify_set;
 static tvh_uuid_set_t  idnode_lnotify_title_set;
 
index 60bc449b5e3e0013aecf9e6b00826142a37eae0e..1a888b01f0b7e5d66b17f785e18d2aee46f0d033 100644 (file)
@@ -41,8 +41,8 @@
 
 #define TRANSPORT_RECOVERY 4 /* in seconds */
 
-static tvh_mutex_t linuxdvb_ca_mutex = { .mutex = PTHREAD_MUTEX_INITIALIZER };
-static tvh_mutex_t linuxdvb_capmt_mutex = { .mutex = PTHREAD_MUTEX_INITIALIZER };
+static tvh_mutex_t linuxdvb_ca_mutex = TVH_THREAD_MUTEX_INITIALIZER;
+static tvh_mutex_t linuxdvb_capmt_mutex = TVH_THREAD_MUTEX_INITIALIZER;
 static th_pipe_t linuxdvb_ca_pipe;
 static pthread_t linuxdvb_ca_threadid;
 static mtimer_t linuxdvb_ca_thread_join_timer;
index 9eeed12ee71626c20809683eaf204a6488cce48d..8677f514c682230296ab2894e595d35df9d3c633 100644 (file)
@@ -500,7 +500,7 @@ lang_code_lookup_t* lang_codes_code2b = NULL;
 lang_code_lookup_t* lang_codes_code1 = NULL;
 lang_code_lookup_t* lang_codes_code2t = NULL;
 
-tvh_mutex_t lang_code_split_mutex = { .mutex = PTHREAD_MUTEX_INITIALIZER };
+tvh_mutex_t lang_code_split_mutex = TVH_THREAD_MUTEX_INITIALIZER;
 RB_HEAD(,lang_code_list) lang_code_split_tree = { NULL, NULL, NULL, 0 };
 
 /* **************************************************************************
index ca54ca4b12abdb2aa3a98f18096a7c48738ce4e8..b6ccb41f97a9f9615c99cffe9404cd981c0b82f9 100644 (file)
@@ -41,7 +41,7 @@
 
 extern char **environ;
 
-tvh_mutex_t spawn_mutex = { .mutex = PTHREAD_MUTEX_INITIALIZER };
+tvh_mutex_t spawn_mutex = TVH_THREAD_MUTEX_INITIALIZER;
 
 static LIST_HEAD(, spawn) spawns;
 
index 9ad31ad8c7340563c3566b444eb41086b3a2672d..a7c5150f5443845393df648547d1916f9671d7d2 100644 (file)
@@ -30,7 +30,7 @@ struct tvh_locale {
 
 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
 
-tvh_mutex_t tvh_gettext_mutex = { .mutex = PTHREAD_MUTEX_INITIALIZER };
+tvh_mutex_t tvh_gettext_mutex = TVH_THREAD_MUTEX_INITIALIZER;
 
 /*
  *
index 83985c24cc4ae89785a920f71927b2c4c5b4b842..c31997c700dd7bf9ba771f742c83226b09b491df 100644 (file)
@@ -30,6 +30,10 @@ static TAILQ_HEAD(, tvh_mutex) thrwatch_mutexes = TAILQ_HEAD_INITIALIZER(thrwatc
 static int64_t tvh_thread_crash_time;
 #endif
 
+#if ENABLE_TRACE
+static void tvh_thread_mutex_failed(tvh_mutex_t *mutex, const char *reason);
+#endif
+
 /*
  * thread routines
  */
@@ -134,14 +138,34 @@ tvh_thread_renice(int value)
   return ret;
 }
 
+#if ENABLE_TRACE
+static void tvh_mutex_check_magic(tvh_mutex_t *mutex)
+{
+  if (mutex &&
+      mutex->magic1 == TVH_THREAD_MUTEX_MAGIC1 &&
+      mutex->magic2 == TVH_THREAD_MUTEX_MAGIC2)
+    return;
+  tvh_thread_mutex_failed(mutex, "magic");
+}
+#else
+static inline void tvh_mutex_check_magic(tvh_mutex_t *mutex)
+{
+}
+#endif
+
 int tvh_mutex_init(tvh_mutex_t *mutex, const pthread_mutexattr_t *attr)
 {
   memset(mutex, 0, sizeof(*mutex));
+#if ENABLE_TRACE
+  mutex->magic1 = TVH_THREAD_MUTEX_MAGIC1;
+  mutex->magic2 = TVH_THREAD_MUTEX_MAGIC2;
+#endif
   return pthread_mutex_init(&mutex->mutex, attr);
 }
 
 int tvh_mutex_destroy(tvh_mutex_t *mutex)
 {
+  tvh_mutex_check_magic(mutex);
   return pthread_mutex_destroy(&mutex->mutex);
 }
 
@@ -224,7 +248,9 @@ tvh_mutex_remove_from_waiters(tvh_mutex_waiter_t *w)
 #if ENABLE_TRACE
 int tvh__mutex_lock(tvh_mutex_t *mutex, const char *filename, int lineno)
 {
-  tvh_mutex_waiter_t *w = tvh_mutex_add_to_waiters(mutex, filename, lineno);
+  tvh_mutex_waiter_t *w;
+  tvh_mutex_check_magic(mutex);
+  w = tvh_mutex_add_to_waiters(mutex, filename, lineno);
   int r = pthread_mutex_lock(&mutex->mutex);
   tvh_mutex_remove_from_waiters(w);
   if (r == 0)
@@ -236,6 +262,7 @@ int tvh__mutex_lock(tvh_mutex_t *mutex, const char *filename, int lineno)
 #if ENABLE_TRACE
 int tvh__mutex_trylock(tvh_mutex_t *mutex, const char *filename, int lineno)
 {
+  tvh_mutex_check_magic(mutex);
   int r = pthread_mutex_trylock(&mutex->mutex);
   if (r == 0)
     tvh_mutex_add_to_list(mutex, filename, lineno);
@@ -246,8 +273,8 @@ int tvh__mutex_trylock(tvh_mutex_t *mutex, const char *filename, int lineno)
 #if ENABLE_TRACE
 int tvh__mutex_unlock(tvh_mutex_t *mutex)
 {
-  int r;
-  r = pthread_mutex_unlock(&mutex->mutex);
+  tvh_mutex_check_magic(mutex);
+  int r = pthread_mutex_unlock(&mutex->mutex);
   if (r == 0)
     tvh_mutex_remove_from_list(mutex, NULL, NULL);
   return r;
@@ -261,6 +288,7 @@ tvh_mutex_timedlock
   int64_t finish = getfastmonoclock() + usec;
   int retcode;
 
+  tvh_mutex_check_magic(mutex);
   while ((retcode = pthread_mutex_trylock (&mutex->mutex)) == EBUSY) {
     if (getfastmonoclock() >= finish)
       return ETIMEDOUT;
@@ -328,6 +356,7 @@ tvh_cond_wait
 #if ENABLE_TRACE
   const char *filename = NULL;
   int lineno = -1;
+  tvh_mutex_check_magic(mutex);
   if (tvh_thread_debug > 0)
     tvh_mutex_remove_from_list(mutex, &filename, &lineno);
 #endif
@@ -348,6 +377,7 @@ tvh_cond_timedwait
 #if ENABLE_TRACE
   const char *filename = NULL;
   int lineno = -1;
+  tvh_mutex_check_magic(mutex);
   if (tvh_thread_debug > 0)
     tvh_mutex_remove_from_list(mutex, &filename, &lineno);
 #endif
@@ -388,6 +418,7 @@ int tvh_cond_timedwait_ts(tvh_cond_t *cond, tvh_mutex_t *mutex, struct timespec
 #if ENABLE_TRACE
   const char *filename = NULL;
   int lineno = -1;
+  tvh_mutex_check_magic(mutex);
   if (tvh_thread_debug > 0)
     tvh_mutex_remove_from_list(mutex, &filename, &lineno);
 #endif
@@ -434,13 +465,14 @@ static void tvh_thread_deadlock_write(htsbuf_queue_t *q)
 #endif
 
 #if ENABLE_TRACE
-static void tvh_thread_mutex_deadlock(tvh_mutex_t *mutex)
+static void tvh_thread_mutex_failed(tvh_mutex_t *mutex, const char *reason)
 {
   htsbuf_queue_t q;
   tvh_mutex_t *m;
   tvh_mutex_waiter_t *w;
 
   htsbuf_queue_init(&q, 0);
+  htsbuf_qprintf(&q, "REASON: %s\n", reason);
   htsbuf_qprintf(&q, "mutex %p locked in: %s:%i (thread %ld)\n", mutex, mutex->filename, mutex->lineno, mutex->tid);
   LIST_FOREACH(w, &mutex->waiters, link)
     htsbuf_qprintf(&q, "mutex %p   waiting in: %s:%i (thread %ld)\n", mutex, w->filename, w->lineno, w->tid);
@@ -468,7 +500,7 @@ static void *tvh_thread_watch_thread(void *aux)
     mutex = TAILQ_LAST(&thrwatch_mutexes, tvh_mutex_queue);
     if (mutex && mutex->tstamp + sec2mono(5) < now) {
       pthread_mutex_unlock(&thrwatch_mutex);
-      tvh_thread_mutex_deadlock(mutex);
+      tvh_thread_mutex_failed(mutex, "deadlock");
     }
     pthread_mutex_unlock(&thrwatch_mutex);
     if (tvh_thread_debug == 12345678 && tvh_thread_crash_time < getfastmonoclock()) {
index b8031528bbf9c5b060e7002345478c33d3187f31..d3a01f18d08f2e8e8242af1c7429e7d6ced60fac 100644 (file)
@@ -25,6 +25,9 @@
 #include "queue.h"
 #include "build.h"
 
+#define TVH_THREAD_MUTEX_MAGIC1 0xd76a338a
+#define TVH_THREAD_MUTEX_MAGIC2 0xf93a6421
+
 typedef struct {
   pthread_cond_t cond;
 } tvh_cond_t;
@@ -44,12 +47,14 @@ typedef struct tvh_mutex_waiter {
 typedef struct tvh_mutex {
   pthread_mutex_t mutex;
 #if ENABLE_TRACE
+  uint32_t magic1;
   long tid;
   const char *filename;
   int lineno;
   int64_t tstamp;
   LIST_HEAD(, tvh_mutex_waiter) waiters;
   TAILQ_ENTRY(tvh_mutex) link;
+  uint32_t magic2;
 #endif
 } tvh_mutex_t;
 
@@ -73,6 +78,18 @@ lock_assert0(tvh_mutex_t *l, const char *file, int line)
 
 #define lock_assert(l) lock_assert0(l, __FILE__, __LINE__)
 
+#if ENABLE_TRACE
+#define TVH_THREAD_MUTEX_INITIALIZER { \
+  .magic1 = TVH_THREAD_MUTEX_MAGIC1, \
+  .magic2 = TVH_THREAD_MUTEX_MAGIC2, \
+  .mutex = PTHREAD_MUTEX_INITIALIZER, \
+}
+#else
+#define TVH_THREAD_MUTEX_INITIALIZER { \
+  .mutex = PTHREAD_MUTEX_INITIALIZER, \
+}
+#endif
+
 /*
  *
  */
index 4dd7e2db50d781a760a8adf5c9bdbfcfd2d69392..5e0ff26ecd1b546e8b6ef0215fb41e504e136246 100644 (file)
@@ -31,7 +31,7 @@
 #include "tcp.h"
 #include "memoryinfo.h"
 
-static tvh_mutex_t comet_mutex = { .mutex = PTHREAD_MUTEX_INITIALIZER };
+static tvh_mutex_t comet_mutex = TVH_THREAD_MUTEX_INITIALIZER;
 static tvh_cond_t comet_cond;
 static int comet_waiting;