diff --git a/src/input/mpegts.h b/src/input/mpegts.h index acbf49db..ac49c844 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -802,6 +802,8 @@ void mpegts_table_flush_all (mpegts_mux_t *mm); void mpegts_table_destroy ( mpegts_table_t *mt ); +void mpegts_table_consistency_check( mpegts_mux_t *mm ); + mpegts_service_t *mpegts_service_create0 ( mpegts_service_t *ms, const idclass_t *class, const char *uuid, mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, htsmsg_t *conf ); diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index c6ef152e..c5aef130 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -655,6 +655,7 @@ mpegts_input_table_waiting ( mpegts_input_t *mi, mpegts_mux_t *mm ) pthread_mutex_lock(&mm->mm_tables_lock); while ((mt = TAILQ_FIRST(&mm->mm_defer_tables)) != NULL) { + mpegts_table_consistency_check(mm); TAILQ_REMOVE(&mm->mm_defer_tables, mt, mt_defer_link); if (mt->mt_defer_cmd == MT_DEFER_OPEN_PID && !mt->mt_destroyed) { mt->mt_defer_cmd = 0; @@ -680,6 +681,7 @@ mpegts_input_table_waiting ( mpegts_input_t *mi, mpegts_mux_t *mm ) mpegts_table_release(mt); pthread_mutex_lock(&mm->mm_tables_lock); } + mpegts_table_consistency_check(mm); pthread_mutex_unlock(&mm->mm_tables_lock); } @@ -925,8 +927,7 @@ mpegts_input_flush_mux } pthread_mutex_unlock(&mi->mi_input_lock); - /* Flush table Q */ - pthread_mutex_lock(&mi->mi_output_lock); + /* Flush table Q - the global lock is already held */ TAILQ_FOREACH(mtf, &mi->mi_table_queue, mtf_link) { if (mtf->mtf_mux == mm) mtf->mtf_mux = NULL; @@ -935,7 +936,6 @@ mpegts_input_flush_mux (mi->mi_destroyed_muxes_count + 1) * sizeof(mpegts_mux_t *)); mi->mi_destroyed_muxes[mi->mi_destroyed_muxes_count++] = mm; - pthread_mutex_unlock(&mi->mi_output_lock); } static void diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 69c2cc6b..37123947 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -838,6 +838,7 @@ mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res ) /* Log */ pthread_mutex_lock(&mm->mm_tables_lock); + mpegts_table_consistency_check(mm); LIST_FOREACH(mt, &mm->mm_tables, mt_link) { if (mt->mt_flags & MT_QUICKREQ) { const char *s = "not found"; @@ -862,7 +863,7 @@ mpegts_mux_scan_timeout ( void *aux ) int c, q; char buf[256]; mpegts_mux_t *mm = aux; - mpegts_table_t *mt, *nxt; + mpegts_table_t *mt; mpegts_mux_nice_name(mm, buf, sizeof(buf)); /* Timeout */ @@ -876,13 +877,15 @@ mpegts_mux_scan_timeout ( void *aux ) /* Check tables */ again: pthread_mutex_lock(&mm->mm_tables_lock); + mpegts_table_consistency_check(mm); c = q = 0; - for (mt = LIST_FIRST(&mm->mm_tables); mt != NULL; mt = nxt) { - nxt = LIST_NEXT(mt, mt_link); + LIST_FOREACH(mt, &mm->mm_tables, mt_link) { if (!(mt->mt_flags & MT_QUICKREQ)) continue; if (!mt->mt_count) { + mpegts_table_grab(mt); pthread_mutex_unlock(&mm->mm_tables_lock); mpegts_table_destroy(mt); + mpegts_table_release(mt); goto again; } else if (!mt->mt_complete) { q++; diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index e7dedb37..3b504edd 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -21,6 +21,26 @@ #include +void +mpegts_table_consistency_check ( mpegts_mux_t *mm ) +{ +#if ENABLE_TRACE + int i, c = 0; + mpegts_table_t *mt; + + lock_assert(&mm->mm_tables_lock); + + i = mm->mm_num_tables; + LIST_FOREACH(mt, &mm->mm_tables, mt_link) + c++; + + if (i != c) { + tvherror("mpegts", "tables count inconsistency (num %d, list %d)", i, c); + abort(); + } +#endif +} + static void mpegts_table_fastswitch ( mpegts_mux_t *mm ) { @@ -131,8 +151,10 @@ mpegts_table_destroy ( mpegts_table_t *mt ) mpegts_mux_t *mm = mt->mt_mux; pthread_mutex_lock(&mm->mm_tables_lock); + mpegts_table_consistency_check(mm); mt->mt_destroyed = 1; mt->mt_mux->mm_close_table(mt->mt_mux, mt); + mpegts_table_consistency_check(mm); pthread_mutex_unlock(&mm->mm_tables_lock); mpegts_table_release(mt); } @@ -165,6 +187,7 @@ mpegts_table_add /* Check for existing */ pthread_mutex_lock(&mm->mm_tables_lock); + mpegts_table_consistency_check(mm); LIST_FOREACH(mt, &mm->mm_tables, mt_link) { if (mt->mt_opaque != opaque) continue; @@ -186,6 +209,7 @@ mpegts_table_add if (!(flags & MT_SKIPSUBS) && !mt->mt_subscribed) mm->mm_open_table(mm, mt, 1); } + mpegts_table_consistency_check(mm); pthread_mutex_unlock(&mm->mm_tables_lock); return mt; } @@ -215,6 +239,7 @@ mpegts_table_add subscribe = 0; } mm->mm_open_table(mm, mt, subscribe); + mpegts_table_consistency_check(mm); pthread_mutex_unlock(&mm->mm_tables_lock); return mt; } @@ -229,6 +254,7 @@ mpegts_table_flush_all ( mpegts_mux_t *mm ) descrambler_flush_tables(mm); pthread_mutex_lock(&mm->mm_tables_lock); + mpegts_table_consistency_check(mm); while ((mt = TAILQ_FIRST(&mm->mm_defer_tables))) { TAILQ_REMOVE(&mm->mm_defer_tables, mt, mt_defer_link); mt->mt_defer_cmd = 0; @@ -237,10 +263,17 @@ mpegts_table_flush_all ( mpegts_mux_t *mm ) while ((mt = LIST_FIRST(&mm->mm_tables))) { mt->mt_flags &= ~MT_DEFER; /* force destroy */ mt->mt_destroyed = 1; /* early destroy mark */ + mpegts_table_grab(mt); + mpegts_table_consistency_check(mm); pthread_mutex_unlock(&mm->mm_tables_lock); mpegts_table_destroy(mt); + mpegts_table_release(mt); pthread_mutex_lock(&mm->mm_tables_lock); + mpegts_table_consistency_check(mm); } + assert(mm->mm_num_tables == 0); + assert(TAILQ_FIRST(&mm->mm_defer_tables) == NULL); + assert(LIST_FIRST(&mm->mm_tables) == NULL); pthread_mutex_unlock(&mm->mm_tables_lock); }