From: Jaroslav Kysela Date: Wed, 14 Oct 2015 07:54:56 +0000 (+0200) Subject: IPTV: fix memory leaks X-Git-Tag: v4.2.1~1920 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=403a43266e266d724863c7b4a69e49a9cc2122af;p=thirdparty%2Ftvheadend.git IPTV: fix memory leaks --- diff --git a/src/http.c b/src/http.c index 370f1903e..211a63dce 100644 --- a/src/http.c +++ b/src/http.c @@ -822,6 +822,19 @@ process_request(http_connection_t *hc, htsbuf_queue_t *spill) +/* + * Delete one argument + */ +void +http_arg_remove(struct http_arg_list *list, struct http_arg *arg) +{ + TAILQ_REMOVE(list, arg, link); + free(arg->key); + free(arg->val); + free(arg); +} + + /* * Delete all arguments associated with a connection */ @@ -829,12 +842,8 @@ void http_arg_flush(struct http_arg_list *list) { http_arg_t *ra; - while((ra = TAILQ_FIRST(list)) != NULL) { - TAILQ_REMOVE(list, ra, link); - free(ra->key); - free(ra->val); - free(ra); - } + while((ra = TAILQ_FIRST(list)) != NULL) + http_arg_remove(list, ra); } diff --git a/src/http.h b/src/http.h index fb53aebaf..6633856e6 100644 --- a/src/http.h +++ b/src/http.h @@ -173,6 +173,7 @@ static inline void http_arg_init(struct http_arg_list *list) TAILQ_INIT(list); } +void http_arg_remove(struct http_arg_list *list, struct http_arg *arg); void http_arg_flush(struct http_arg_list *list); char *http_arg_get(struct http_arg_list *list, const char *name); diff --git a/src/input/mpegts.h b/src/input/mpegts.h index b5ff390f2..283ecb720 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -307,6 +307,7 @@ struct mpegts_network /* * Functions */ + void (*mn_delete) (mpegts_network_t*, int delconf); void (*mn_display_name) (mpegts_network_t*, char *buf, size_t len); void (*mn_config_save) (mpegts_network_t*); mpegts_mux_t* (*mn_create_mux) diff --git a/src/input/mpegts/iptv/iptv.c b/src/input/mpegts/iptv/iptv.c index d5bb165c0..46475a212 100644 --- a/src/input/mpegts/iptv/iptv.c +++ b/src/input/mpegts/iptv/iptv.c @@ -477,30 +477,37 @@ iptv_input_mux_started ( iptv_mux_t *im ) im->mm_iptv_atsc ? DVB_SYS_ATSC_ALL : DVB_SYS_DVBT); } -/* ************************************************************************** - * IPTV network - * *************************************************************************/ - static void -iptv_network_class_delete ( idnode_t *in ) +iptv_network_delete ( mpegts_network_t *mn, int delconf ) { - iptv_network_t *mn = (iptv_network_t*)in; - char *s = mn->in_url; + iptv_network_t *in = (iptv_network_t*)mn; + char *s = in->in_url; - if (in->in_class == &iptv_auto_network_class) - iptv_auto_network_done((iptv_network_t *)in); + if (in->mn_id.in_class == &iptv_auto_network_class) + iptv_auto_network_done(in); /* Remove config */ - hts_settings_remove("input/iptv/networks/%s", - idnode_uuid_as_sstr(in)); + if (delconf) + hts_settings_remove("input/iptv/networks/%s", + idnode_uuid_as_sstr(&in->mn_id)); /* delete */ - free(mn->in_remove_args); - mpegts_network_delete((mpegts_network_t *)mn, 1); + free(in->in_remove_args); + mpegts_network_delete(mn, delconf); free(s); } +/* ************************************************************************** + * IPTV network + * *************************************************************************/ + +static void +iptv_network_class_delete ( idnode_t *in ) +{ + return iptv_network_delete((mpegts_network_t *)in, 1); +} + extern const idclass_t mpegts_network_class; const idclass_t iptv_network_class = { .ic_super = &mpegts_network_class, @@ -640,6 +647,7 @@ iptv_network_create0 free(in); return NULL; } + in->mn_delete = iptv_network_delete; in->mn_create_service = iptv_network_create_service; in->mn_mux_class = iptv_network_mux_class; in->mn_mux_create2 = iptv_network_create_mux2; @@ -747,7 +755,9 @@ void iptv_done ( void ) pthread_join(iptv_thread, NULL); tvhpoll_destroy(iptv_poll); pthread_mutex_lock(&global_lock); + mpegts_network_unregister_builder(&iptv_auto_network_class); mpegts_network_unregister_builder(&iptv_network_class); + mpegts_network_class_delete(&iptv_auto_network_class, 0); mpegts_network_class_delete(&iptv_network_class, 0); mpegts_input_stop_all((mpegts_input_t*)iptv_input); mpegts_input_delete((mpegts_input_t *)iptv_input, 0); diff --git a/src/input/mpegts/iptv/iptv_auto.c b/src/input/mpegts/iptv/iptv_auto.c index 5af2a9b85..aa89685ea 100644 --- a/src/input/mpegts/iptv/iptv_auto.c +++ b/src/input/mpegts/iptv/iptv_auto.c @@ -63,7 +63,7 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in, if (urlparse(url, &u)) return; if (u.host == NULL || u.host[0] == '\0') - return; + goto end; /* remove requested arguments */ if (!http_args_empty(remove_args)) { @@ -73,7 +73,7 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in, for (ra2 = TAILQ_FIRST(&args); ra2; ra2 = ra2_next) { ra2_next = TAILQ_NEXT(ra2, link); if (strcmp(ra1->key, ra2->key) == 0) - TAILQ_REMOVE(&args, ra2, link); + http_arg_remove(&args, ra2); } free(u.query); u.query = NULL; @@ -90,6 +90,7 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in, u.query = htsbuf_to_string(&q); htsbuf_queue_flush(&q); } + http_arg_flush(&args); tvh_strlcatf(url2, sizeof(url2), l, "%s://", u.scheme); if (u.user && u.user[0] && u.pass && u.pass[0]) tvh_strlcatf(url2, sizeof(url2), l, "%s:%s@", u.user, u.pass); @@ -129,7 +130,7 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in, if (change) idnode_notify_changed(&im->mm_id); (*total)++; - return; + goto end; } } @@ -146,6 +147,9 @@ iptv_auto_network_process_m3u_item(iptv_network_t *in, (*total)++; (*count)++; } + +end: + urlreset(&u); } /* @@ -224,6 +228,8 @@ iptv_auto_network_process(iptv_network_t *in, const char *last_url, char *data, if (!strncmp(data, "#EXTM3U", 7)) r = iptv_auto_network_process_m3u(in, data, last_url, &remove_args, in->in_channel_number); + http_arg_flush(&remove_args); + if (r == 0) { count = 0; LIST_FOREACH(mm, &in->mn_muxes, mm_network_link) @@ -247,7 +253,7 @@ iptv_auto_network_process(iptv_network_t *in, const char *last_url, char *data, static int iptv_auto_network_file(iptv_network_t *in, const char *filename) { - int fd; + int fd, res; struct stat st; char *data, *last_url; size_t r; @@ -283,9 +289,12 @@ iptv_auto_network_file(iptv_network_t *in, const char *filename) last_url = strrchr(filename, '/'); if (last_url) last_url++; - return iptv_auto_network_process(in, last_url, data, off); + res = iptv_auto_network_process(in, last_url, data, off); + } else { + res = -1; } - return -1; + free(data); + return res; } /* @@ -329,6 +338,9 @@ iptv_auto_network_fetch_complete(http_client_t *hc) pthread_mutex_lock(&global_lock); + if (in->in_http_client == NULL) + goto out; + if (hc->hc_code == HTTP_STATUS_OK && hc->hc_result == 0 && hc->hc_data_size > 0) iptv_auto_network_process(in, last_url, hc->hc_data, hc->hc_data_size); else @@ -338,8 +350,10 @@ iptv_auto_network_fetch_complete(http_client_t *hc) /* note: http_client_close must be called outside http_client callbacks */ gtimer_arm(&in->in_fetch_timer, iptv_auto_network_fetch_done, hc, 0); +out: pthread_mutex_unlock(&global_lock); + urlreset(&u); return 0; } @@ -353,6 +367,8 @@ iptv_auto_network_fetch(void *aux) http_client_t *hc; url_t u; + memset(&u, 0, sizeof(u)); + if (strncmp(in->in_url, "file://", 7) == 0) { iptv_auto_network_file(in, in->in_url + 7); goto arm; @@ -364,7 +380,6 @@ iptv_auto_network_fetch(void *aux) in->in_http_client = NULL; } - memset(&u, 0, sizeof(u)); if (urlparse(in->in_url, &u) < 0) { tvherror("iptv", "wrong url for network '%s'", in->mn_network_name); goto arm; @@ -388,6 +403,7 @@ iptv_auto_network_fetch(void *aux) in->in_http_client = hc; arm: + urlreset(&u); gtimer_arm(&in->in_auto_timer, iptv_auto_network_fetch, in, MAX(1, in->in_refetch_period) * 60); } @@ -407,10 +423,10 @@ iptv_auto_network_init( iptv_network_t *in ) void iptv_auto_network_done( iptv_network_t *in ) { - gtimer_disarm(&in->in_auto_timer); - gtimer_disarm(&in->in_fetch_timer); if (in->in_http_client) { http_client_close(in->in_http_client); in->in_http_client = NULL; } + gtimer_disarm(&in->in_auto_timer); + gtimer_disarm(&in->in_fetch_timer); } diff --git a/src/input/mpegts/iptv/iptv_http.c b/src/input/mpegts/iptv/iptv_http.c index 4f78fb89c..8ca7a566a 100644 --- a/src/input/mpegts/iptv/iptv_http.c +++ b/src/input/mpegts/iptv/iptv_http.c @@ -146,6 +146,7 @@ iptv_http_complete } else { tvherror("iptv", "m3u url invalid '%s'", url); } + urlreset(&u); free(url); return 0; } diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index 98ae3ad0c..f98418ee2 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -357,6 +357,7 @@ mpegts_network_create0 mn->mn_create_service = mpegts_network_create_service; mn->mn_mux_class = mpegts_network_mux_class; mn->mn_mux_create2 = mpegts_network_mux_create2; + mn->mn_delete = mpegts_network_delete; /* Add to global list */ LIST_INSERT_HEAD(&mpegts_network_all, mn, mn_global_link); @@ -389,7 +390,7 @@ mpegts_network_class_delete(const idclass_t *idc, int delconf) for (mn = LIST_FIRST(&mpegts_network_all); mn != NULL; mn = n) { n = LIST_NEXT(mn, mn_global_link); if (mn->mn_id.in_class == idc) - mpegts_network_delete(mn, delconf); + mn->mn_delete(mn, delconf); } }