Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
mpegts mux: protect mux free using refcouting
  • Loading branch information
perexg committed Jul 1, 2016
1 parent 343c3ea commit 70b879b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 17 deletions.
21 changes: 21 additions & 0 deletions src/input/mpegts.h
Expand Up @@ -419,6 +419,7 @@ typedef struct tsdebug_packet {
struct mpegts_mux
{
idnode_t mm_id;
int mm_refcount;

/*
* Identification
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 );
Expand Down
31 changes: 19 additions & 12 deletions src/input/mpegts/iptv/iptv_mux.c
Expand Up @@ -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 )
{
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 8 additions & 1 deletion src/input/mpegts/mpegts_input.c
Expand Up @@ -1127,6 +1127,7 @@ mpegts_input_recv_packets
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 {
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
17 changes: 13 additions & 4 deletions src/input/mpegts/mpegts_mux.c
Expand Up @@ -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 )
{
Expand All @@ -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 *
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit 70b879b

Please sign in to comment.