]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts tables: fix the deferred tables locking mechanism
authorJaroslav Kysela <perex@perex.cz>
Fri, 25 Jul 2014 18:53:34 +0000 (20:53 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 25 Jul 2014 18:53:34 +0000 (20:53 +0200)
src/input/mpegts.h
src/input/mpegts/mpegts_input.c
src/input/mpegts/mpegts_mux.c
src/input/mpegts/mpegts_table.c

index 258e524b84b946f1759c97fb7857468235bcf40b..bcd56c0071e06ea7157f8ca1430c74c7a78799f6 100644 (file)
@@ -179,7 +179,9 @@ struct mpegts_table
   uint8_t mt_finished;
   uint8_t mt_subscribed;
   uint8_t mt_defer_cmd;
-  uint8_t mt_defer_reg;
+
+#define MT_DEFER_OPEN_PID  1
+#define MT_DEFER_CLOSE_PID 2
 
   int mt_count;
 
@@ -769,6 +771,8 @@ static inline void mpegts_table_release
   assert(mt->mt_refcount > 0);
   if(--mt->mt_refcount == 0) mpegts_table_release_(mt);
 }
+int mpegts_table_type
+  ( mpegts_table_t *mt );
 mpegts_table_t *mpegts_table_add
   (mpegts_mux_t *mm, int tableid, int mask,
    mpegts_table_callback_t callback, void *opaque,
index 2cfa2a0a309101a92748fb3a2c7629caddb62670..55caae257672a5da4b9181ad73fd70034155c97c 100644 (file)
@@ -590,37 +590,23 @@ static void
 mpegts_input_table_waiting ( mpegts_input_t *mi, mpegts_mux_t *mm )
 {
   mpegts_table_t *mt;
-  int type;
 
   pthread_mutex_lock(&mm->mm_tables_lock);
   while ((mt = LIST_FIRST(&mm->mm_defer_tables)) != NULL) {
     LIST_REMOVE(mt, mt_defer_link);
-    if (mt->mt_destroyed)
-      continue;
-    type = 0;
-    if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
-    if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
-    if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
-    if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
-    if (mt->mt_defer_cmd == 1) {
+    if (mt->mt_defer_cmd == MT_DEFER_OPEN_PID && !mt->mt_destroyed) {
       mt->mt_defer_cmd = 0;
-      mt->mt_defer_reg = 1;
-      LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
-      mm->mm_num_tables++;
       if (!mt->mt_subscribed) {
         mt->mt_subscribed = 1;
         pthread_mutex_unlock(&mm->mm_tables_lock);
-        mi->mi_open_pid(mi, mm, mt->mt_pid, type, mt);
+        mi->mi_open_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
       }
-    } else if (mt->mt_defer_cmd == 2) {
+    } else if (mt->mt_defer_cmd == MT_DEFER_CLOSE_PID) {
       mt->mt_defer_cmd = 0;
-      mt->mt_defer_reg = 0;
-      LIST_REMOVE(mt, mt_link);
-      mm->mm_num_tables--;
       if (mt->mt_subscribed) {
         mt->mt_subscribed = 0;
         pthread_mutex_unlock(&mm->mm_tables_lock);
-        mi->mi_close_pid(mi, mm, mt->mt_pid, type, mt);
+        mi->mi_close_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
       }
     } else {
       pthread_mutex_unlock(&mm->mm_tables_lock);
index 3744cf9771b479ca94960787b3d22b742a63244c..01a92b3a00231eed0e3ac9676aa29676cee6e810 100644 (file)
@@ -708,13 +708,12 @@ void
 mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe )
 {
   mpegts_input_t *mi;
-  int type = 0;
 
-  if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
-  if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
-  if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
-  if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
   pthread_mutex_lock(&mm->mm_tables_lock);
+  if (mt->mt_destroyed) {
+    pthread_mutex_unlock(&mm->mm_tables_lock);
+    return;
+  }
   if (!mm->mm_active || !mm->mm_active->mmi_input) {
     mt->mt_subscribed = 0;
     LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
@@ -723,12 +722,14 @@ mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe )
     return;
   }
   if (mt->mt_flags & MT_DEFER) {
-    if (mt->mt_defer_reg || mt->mt_defer_cmd == 1) {
+    if (mt->mt_defer_cmd == MT_DEFER_OPEN_PID) {
       pthread_mutex_unlock(&mm->mm_tables_lock);
       return;
     }
     mpegts_table_grab(mt); /* thread will release the table */
-    mt->mt_defer_cmd = 1;
+    LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
+    mm->mm_num_tables++;
+    mt->mt_defer_cmd = MT_DEFER_OPEN_PID;
     LIST_INSERT_HEAD(&mm->mm_defer_tables, mt, mt_defer_link);
     pthread_mutex_unlock(&mm->mm_tables_lock);
     return;
@@ -739,7 +740,7 @@ mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe )
   pthread_mutex_unlock(&mm->mm_tables_lock);
   pthread_mutex_lock(&mi->mi_output_lock);
   if (subscribe) {
-    mi->mi_open_pid(mi, mm, mt->mt_pid, type, mt);
+    mi->mi_open_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
     mt->mt_subscribed = 1;
   }
   pthread_mutex_unlock(&mi->mi_output_lock);
@@ -749,14 +750,13 @@ void
 mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
 {
   mpegts_input_t *mi;
-  int type = 0;
 
-  if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
-  if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
-  if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
-  if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
   pthread_mutex_lock(&mm->mm_tables_lock);
   if (!mm->mm_active || !mm->mm_active->mmi_input) {
+    if (mt->mt_defer_cmd) {
+      LIST_REMOVE(mt, mt_defer_link);
+      mt->mt_defer_cmd = 0;
+    }
     mt->mt_subscribed = 0;
     LIST_REMOVE(mt, mt_link);
     mm->mm_num_tables--;
@@ -764,23 +764,21 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
     return;
   }
   if (mt->mt_flags & MT_DEFER) {
-    if (mt->mt_defer_cmd == 2) {
+    if (mt->mt_defer_cmd == MT_DEFER_CLOSE_PID) {
       pthread_mutex_unlock(&mm->mm_tables_lock);
       return;
     }
-    if (mt->mt_defer_cmd == 1) {
+    if (mt->mt_defer_cmd == MT_DEFER_OPEN_PID) {
       LIST_REMOVE(mt, mt_defer_link);
       mt->mt_defer_cmd = 0;
       pthread_mutex_unlock(&mm->mm_tables_lock);
       mpegts_table_release(mt);
       return;
     }
-    if (!mt->mt_defer_reg) {
-      pthread_mutex_unlock(&mm->mm_tables_lock);
-      return;
-    }
-    mpegts_table_grab(mt); /* thread will release the table */
-    mt->mt_defer_cmd = 2;
+    mpegts_table_grab(mt); /* thread will free the table */
+    LIST_REMOVE(mt, mt_link);
+    mm->mm_num_tables--;
+    mt->mt_defer_cmd = MT_DEFER_CLOSE_PID;
     LIST_INSERT_HEAD(&mm->mm_defer_tables, mt, mt_defer_link);
     pthread_mutex_unlock(&mm->mm_tables_lock);
     return;
@@ -791,7 +789,7 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
   pthread_mutex_unlock(&mm->mm_tables_lock);
   pthread_mutex_lock(&mi->mi_output_lock);
   if (mt->mt_subscribed) {
-    mi->mi_close_pid(mi, mm, mt->mt_pid, type, mt);
+    mi->mi_close_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
     mt->mt_subscribed = 0;
   }
   pthread_mutex_unlock(&mi->mi_output_lock);
index 89f100f5755d8402245d8fd46ae1e13ee29880c2..4fea27c19d515ce47a3c2d241efa0a71ed567d92 100644 (file)
@@ -126,6 +126,19 @@ mpegts_table_destroy ( mpegts_table_t *mt )
   mpegts_table_release(mt);
 }
 
+/**
+ * Determine table type
+ */
+int
+mpegts_table_type ( mpegts_table_t *mt )
+{
+  int type = 0;
+  if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
+  if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
+  if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
+  if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
+  return type;
+}
 
 /**
  * Add a new DVB table
@@ -206,26 +219,38 @@ void
 mpegts_table_flush_all ( mpegts_mux_t *mm )
 {
   mpegts_table_t        *mt;
+  mpegts_input_t        *mi;
+
   descrambler_flush_tables(mm);
+  mi = mm->mm_active ? mm->mm_active->mmi_input : NULL;
   pthread_mutex_lock(&mm->mm_tables_lock);
   while ((mt = LIST_FIRST(&mm->mm_defer_tables))) {
     LIST_REMOVE(mt, mt_defer_link);
-    if (!mt->mt_defer_reg) {
-      /* registration not fished, but ... */
-      /* allow the table free in next table destroy loop */
-      mt->mt_defer_reg = 1;
-      LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
-      mm->mm_num_tables++;
+    if (mt->mt_defer_cmd == MT_DEFER_CLOSE_PID) {
+      if (mi) {
+        pthread_mutex_unlock(&mm->mm_tables_lock);
+        pthread_mutex_lock(&mi->mi_output_lock);
+        if (mt->mt_subscribed) {
+          mi->mi_close_pid(mi, mm, mt->mt_pid, mpegts_table_type(mt), mt);
+          mt->mt_subscribed = 0;
+        }
+        pthread_mutex_unlock(&mi->mi_output_lock);
+        pthread_mutex_lock(&mm->mm_tables_lock);
+      } else{
+        mt->mt_subscribed = 0;
+      }
     }
     mt->mt_defer_cmd = 0;
     mpegts_table_release(mt);
   }
-  pthread_mutex_unlock(&mm->mm_tables_lock);
   while ((mt = LIST_FIRST(&mm->mm_tables))) {
-    if ((mt->mt_flags & MT_DEFER) && mt->mt_defer_reg)
-      mt->mt_flags &= ~MT_DEFER; /* force destroy */
+    mt->mt_flags &= ~MT_DEFER; /* force destroy */
+    mt->mt_destroyed = 1;      /* early destroy mark */
+    pthread_mutex_unlock(&mm->mm_tables_lock);
     mpegts_table_destroy(mt);
+    pthread_mutex_lock(&mm->mm_tables_lock);
   }
+  pthread_mutex_unlock(&mm->mm_tables_lock);
 }
 
 /*