]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts: fix the table locking
authorJaroslav Kysela <perex@perex.cz>
Wed, 18 Jun 2014 12:31:45 +0000 (14:31 +0200)
committerJaroslav Kysela <perex@perex.cz>
Wed, 18 Jun 2014 12:41:32 +0000 (14:41 +0200)
The table must be inserted/removed in the mi_output_lock protection, because
mpegts_input_table_dispatch() requires the consistent list and the count of tables
(see assert).

src/input/mpegts.h
src/input/mpegts/mpegts_mux.c
src/input/mpegts/mpegts_table.c

index c5a7b626e68f27ed3c888b2e6db1e8141c477689..7a4a7c381f0d2f6acb613fdd1346806ac16996e0 100644 (file)
@@ -374,7 +374,7 @@ struct mpegts_mux
   int  (*mm_is_enabled)       (mpegts_mux_t *mm);
   int  (*mm_start)            (mpegts_mux_t *mm, const char *r, int w);
   void (*mm_stop)             (mpegts_mux_t *mm, int force);
-  void (*mm_open_table)       (mpegts_mux_t*,mpegts_table_t*);
+  void (*mm_open_table)       (mpegts_mux_t*,mpegts_table_t*,int subscribe);
   void (*mm_close_table)      (mpegts_mux_t*,mpegts_table_t*);
   void (*mm_create_instances) (mpegts_mux_t*);
 
@@ -688,7 +688,7 @@ int mpegts_mux_set_tsid ( mpegts_mux_t *mm, uint16_t tsid, int force );
 int mpegts_mux_set_onid ( mpegts_mux_t *mm, uint16_t onid );
 int mpegts_mux_set_crid_authority ( mpegts_mux_t *mm, const char *defauth );
 
-void mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt );
+void mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe );
 void mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt );
 
 void mpegts_mux_remove_subscriber(mpegts_mux_t *mm, th_subscription_t *s, int reason);
index 698b147ec18790fca4dbf41cb8e29231a4ec42d6..084e5eeecbacf597fd31d854a18b1c31e16de8d8 100644 (file)
@@ -673,18 +673,29 @@ mpegts_mux_stop ( mpegts_mux_t *mm, int force )
 }
 
 void
-mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt )
+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;
-  mpegts_input_t *mi;
-  if (!mm->mm_active || !mm->mm_active->mmi_input) return;
+  if (!mm->mm_active || !mm->mm_active->mmi_input) {
+    mt->mt_subscribed = 0;
+    LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
+    mm->mm_num_tables++;
+    return;
+  }
   mi = mm->mm_active->mmi_input;
   pthread_mutex_lock(&mi->mi_output_lock);
-  mi->mi_open_pid(mi, mm, mt->mt_pid, type, mt);
+  LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
+  mm->mm_num_tables++;
+  if (subscribe) {
+    mi->mi_open_pid(mi, mm, mt->mt_pid, type, mt);
+    mt->mt_subscribed = 1;
+  }
   pthread_mutex_unlock(&mi->mi_output_lock);
 }
 
@@ -693,14 +704,25 @@ 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;
-  if (!mm->mm_active || !mm->mm_active->mmi_input) return;
+  if (!mm->mm_active || !mm->mm_active->mmi_input) {
+    mt->mt_subscribed = 0;
+    LIST_REMOVE(mt, mt_link);
+    mm->mm_num_tables--;
+    return;
+  }
   mi = mm->mm_active->mmi_input;
   pthread_mutex_lock(&mi->mi_output_lock);
-  mi->mi_close_pid(mi, mm, mt->mt_pid, type, mt);
+  LIST_REMOVE(mt, mt_link);
+  mm->mm_num_tables--;
+  if (mt->mt_subscribed) {
+    mi->mi_close_pid(mi, mm, mt->mt_pid, type, mt);
+    mt->mt_subscribed = 0;
+  }
   pthread_mutex_unlock(&mi->mi_output_lock);
 }
 
index 6f1f11b72fba82eabce7820bcdc6e3b000e66d58..71d945a7695b12a0b0fa5c0af6b12c78a8df1554 100644 (file)
@@ -104,11 +104,8 @@ void
 mpegts_table_destroy ( mpegts_table_t *mt )
 {
   struct mpegts_table_state *st;
-  LIST_REMOVE(mt, mt_link);
   mt->mt_destroyed = 1;
-  mt->mt_mux->mm_num_tables--;
-  if (mt->mt_subscribed)
-    mt->mt_mux->mm_close_table(mt->mt_mux, mt);
+  mt->mt_mux->mm_close_table(mt->mt_mux, mt);
   while ((st = RB_FIRST(&mt->mt_state))) {
     RB_REMOVE(&mt->mt_state, st, link);
     free(st);
@@ -141,8 +138,7 @@ mpegts_table_add
       mt->mt_callback   = callback;
       mt->mt_pid        = pid;
       mt->mt_table      = tableid;
-      mt->mt_subscribed = 1;
-      mm->mm_open_table(mm, mt);
+      mm->mm_open_table(mm, mt, 1);
     } else if (pid >= 0) {
       if (mt->mt_pid != pid)
         continue;
@@ -151,10 +147,8 @@ mpegts_table_add
     } else {
       if (strcmp(mt->mt_name, name))
         continue;
-      if (!(flags & MT_SKIPSUBS) && !mt->mt_subscribed) {
-        mt->mt_subscribed = 1;
-        mm->mm_open_table(mm, mt);
-      }
+      if (!(flags & MT_SKIPSUBS) && !mt->mt_subscribed)
+        mm->mm_open_table(mm, mt, 1);
     }
     return mt;
   }
@@ -174,8 +168,6 @@ mpegts_table_add
   mt->mt_mask     = mask;
   mt->mt_mux      = mm;
   mt->mt_cc       = -1;
-  LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
-  mm->mm_num_tables++;
 
   /* Open table */
   if (pid < 0) {
@@ -186,10 +178,7 @@ mpegts_table_add
     if (mm->mm_scan_state == MM_SCAN_STATE_IDLE)
       subscribe = 0;
   }
-  if (subscribe) {
-    mt->mt_subscribed = 1;
-    mm->mm_open_table(mm, mt);
-  }
+  mm->mm_open_table(mm, mt, subscribe);
   return mt;
 }