From: Jaroslav Kysela Date: Fri, 1 Jul 2016 08:50:00 +0000 (+0200) Subject: mpegts mux: protect mux free using refcouting X-Git-Tag: v4.2.1~406 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=70b879bf7520287189270292ec333cb13a434ca9;p=thirdparty%2Ftvheadend.git mpegts mux: protect mux free using refcouting --- diff --git a/src/input/mpegts.h b/src/input/mpegts.h index a12bafc27..7f512e97e 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -419,6 +419,7 @@ typedef struct tsdebug_packet { struct mpegts_mux { idnode_t mm_id; + int mm_refcount; /* * Identification @@ -506,6 +507,7 @@ struct mpegts_mux */ void (*mm_delete) (mpegts_mux_t *mm, int delconf); + void (*mm_free) (mpegts_mux_t *mm); htsmsg_t *(*mm_config_save) (mpegts_mux_t *mm, char *filename, size_t fsize); void (*mm_display_name) (mpegts_mux_t*, char *buf, size_t len); int (*mm_is_enabled) (mpegts_mux_t *mm); @@ -877,6 +879,25 @@ static inline mpegts_mux_t *mpegts_mux_find(const char *uuid) void mpegts_mux_delete ( mpegts_mux_t *mm, int delconf ); +void mpegts_mux_free ( mpegts_mux_t *mm ); + +static inline void mpegts_mux_grab ( mpegts_mux_t *mm ) +{ + int v = atomic_add(&mm->mm_refcount, 1); + assert(v > 0); +} + +static inline int mpegts_mux_release ( mpegts_mux_t *mm ) +{ + int v = atomic_dec(&mm->mm_refcount, 1); + assert(v > 0); + if (v == 1) { + mm->mm_free(mm); + return 1; + } + return 0; +} + void mpegts_mux_save ( mpegts_mux_t *mm, htsmsg_t *c ); void mpegts_mux_tuning_error( const char *mux_uuid, mpegts_mux_instance_t *mmi_match ); diff --git a/src/input/mpegts/iptv/iptv_mux.c b/src/input/mpegts/iptv/iptv_mux.c index 984628e46..91335ad62 100644 --- a/src/input/mpegts/iptv/iptv_mux.c +++ b/src/input/mpegts/iptv/iptv_mux.c @@ -274,6 +274,24 @@ iptv_mux_config_save ( mpegts_mux_t *mm, char *filename, size_t fsize ) return c; } +static void +iptv_mux_free ( mpegts_mux_t *mm ) +{ + iptv_mux_t *im = (iptv_mux_t *)mm; + free(im->mm_iptv_url); + free(im->mm_iptv_url_sane); + free(im->mm_iptv_url_raw); + free(im->mm_iptv_muxname); + free(im->mm_iptv_interface); + free(im->mm_iptv_svcname); + free(im->mm_iptv_env); + free(im->mm_iptv_hdr); + free(im->mm_iptv_tags); + free(im->mm_iptv_icon); + free(im->mm_iptv_epgid); + mpegts_mux_free(mm); +} + static void iptv_mux_delete ( mpegts_mux_t *mm, int delconf ) { @@ -286,19 +304,7 @@ iptv_mux_delete ( mpegts_mux_t *mm, int delconf ) idnode_uuid_as_str(&mm->mm_network->mn_id, ubuf1), idnode_uuid_as_str(&mm->mm_id, ubuf2)); - copy = *im; /* keep pointers */ mpegts_mux_delete(mm, delconf); - free(copy.mm_iptv_url); - free(copy.mm_iptv_url_sane); - free(copy.mm_iptv_url_raw); - free(copy.mm_iptv_muxname); - free(copy.mm_iptv_interface); - free(copy.mm_iptv_svcname); - free(copy.mm_iptv_env); - free(copy.mm_iptv_hdr); - free(copy.mm_iptv_tags); - free(copy.mm_iptv_icon); - free(copy.mm_iptv_epgid); } static void @@ -336,6 +342,7 @@ iptv_mux_create0 ( iptv_network_t *in, const char *uuid, htsmsg_t *conf ) im->mm_display_name = iptv_mux_display_name; im->mm_config_save = iptv_mux_config_save; im->mm_delete = iptv_mux_delete; + im->mm_free = iptv_mux_free; if (!im->mm_iptv_kill_timeout) im->mm_iptv_kill_timeout = 5; diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index a9d599a9b..854b200a1 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -1127,6 +1127,7 @@ retry: if (mi->mi_input_queue_size < 50*1024*1024) { mi->mi_input_queue_size += len2; memoryinfo_alloc(&mpegts_input_queue_memoryinfo, sizeof(mpegts_packet_t) + len2); + mpegts_mux_grab(mp->mp_mux); TAILQ_INSERT_TAIL(&mi->mi_input_queue, mp, mp_link); tvh_cond_signal(&mi->mi_input_cond, 0); } else { @@ -1513,6 +1514,8 @@ mpegts_input_thread ( void * p ) } /* Cleanup */ + if (mp->mp_mux) + mpegts_mux_release(mp->mp_mux); free(mp); #if ENABLE_TSDEBUG @@ -1531,6 +1534,8 @@ mpegts_input_thread ( void * p ) while ((mp = TAILQ_FIRST(&mi->mi_input_queue))) { memoryinfo_free(&mpegts_input_queue_memoryinfo, sizeof(mpegts_packet_t) + mp->mp_len); TAILQ_REMOVE(&mi->mi_input_queue, mp, mp_link); + if (mp->mp_mux) + mpegts_mux_release(mp->mp_mux); free(mp); } mi->mi_input_queue_size = 0; @@ -1606,8 +1611,10 @@ mpegts_input_flush_mux /* Flush input Q */ pthread_mutex_lock(&mi->mi_input_lock); TAILQ_FOREACH(mp, &mi->mi_input_queue, mp_link) { - if (mp->mp_mux == mm) + if (mp->mp_mux == mm) { + mpegts_mux_release(mm); mp->mp_mux = NULL; + } } pthread_mutex_unlock(&mi->mi_input_lock); diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 1b72710dd..b155c77e9 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -721,6 +721,15 @@ mpegts_mux_do_stop ( mpegts_mux_t *mm, int delconf ) mtimer_disarm(&mm->mm_update_pids_timer); } +void +mpegts_mux_free ( mpegts_mux_t *mm ) +{ + free(mm->mm_provider_network_name); + free(mm->mm_crid_authority); + free(mm->mm_charset); + free(mm); +} + void mpegts_mux_delete ( mpegts_mux_t *mm, int delconf ) { @@ -743,10 +752,7 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf ) /* Free memory */ idnode_save_check(&mm->mm_id, 1); idnode_unlink(&mm->mm_id); - free(mm->mm_provider_network_name); - free(mm->mm_crid_authority); - free(mm->mm_charset); - free(mm); + mpegts_mux_release(mm); } static htsmsg_t * @@ -1168,6 +1174,8 @@ mpegts_mux_create0 return NULL; } + mm->mm_refcount = 1; + /* Enabled by default */ mm->mm_enabled = MM_ENABLE; mm->mm_epg = MM_EPG_ENABLE; @@ -1182,6 +1190,7 @@ mpegts_mux_create0 /* Debug/Config */ mm->mm_delete = mpegts_mux_delete; + mm->mm_free = mpegts_mux_free; mm->mm_display_name = mpegts_mux_display_name; mm->mm_config_save = mpegts_mux_config_save; mm->mm_is_enabled = mpegts_mux_is_enabled;