Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Graceful exit
It's necessary to do serious checks for the memory leaks using
tools like valgrind. This patch tries to implement a graceful
exit for all tvheadend components and free allocated memory.

Also, some memory leaks were fixed.
  • Loading branch information
perexg committed Feb 17, 2014
1 parent 56a39c5 commit c07824a
Show file tree
Hide file tree
Showing 93 changed files with 1,268 additions and 290 deletions.
11 changes: 11 additions & 0 deletions src/access.c
Expand Up @@ -520,6 +520,7 @@ access_entry_destroy(access_entry_t *ae)
free(ae->ae_id);
free(ae->ae_username);
free(ae->ae_password);
free(ae->ae_comment);
TAILQ_REMOVE(&access_entries, ae, ae_link);
free(ae);
}
Expand Down Expand Up @@ -769,3 +770,13 @@ access_init(int createdefault, int noacl)
htsmsg_destroy(m);
}
}

void
access_done(void)
{
access_entry_t *ae;

dtable_delete("accesscontrol");
while ((ae = TAILQ_FIRST(&access_entries)) != NULL)
access_entry_destroy(ae);
}
1 change: 1 addition & 0 deletions src/access.h
Expand Up @@ -111,5 +111,6 @@ uint32_t access_get_by_addr(struct sockaddr *src);
*
*/
void access_init(int createdefault, int noacl);
void access_done(void);

#endif /* ACCESS_H_ */
28 changes: 20 additions & 8 deletions src/api.c
Expand Up @@ -29,6 +29,7 @@ typedef struct api_link {
} api_link_t;

RB_HEAD(,api_link) api_hook_tree;
SKEL_DECLARE(api_skel, api_link_t);

static int ah_cmp
( api_link_t *a, api_link_t *b )
Expand All @@ -39,15 +40,15 @@ static int ah_cmp
void
api_register ( const api_hook_t *hook )
{
static api_link_t *t, *skel = NULL;
if (!skel)
skel = calloc(1, sizeof(api_link_t));
skel->hook = hook;
t = RB_INSERT_SORTED(&api_hook_tree, skel, link, ah_cmp);
if (t)
api_link_t *t;
SKEL_ALLOC(api_skel);
api_skel->hook = hook;
t = RB_INSERT_SORTED(&api_hook_tree, api_skel, link, ah_cmp);
if (t) {
tvherror("api", "trying to re-register subsystem");
else
skel = NULL;
} else {
SKEL_USED(api_skel);
}
}

void
Expand Down Expand Up @@ -125,3 +126,14 @@ void api_init ( void )
api_status_init();
api_imagecache_init();
}

void api_done ( void )
{
api_link_t *t;

while ((t = RB_FIRST(&api_hook_tree)) != NULL) {
RB_REMOVE(&api_hook_tree, t, link);
free(t);
}
SKEL_FREE(api_skel);
}
1 change: 1 addition & 0 deletions src/api.h
Expand Up @@ -56,6 +56,7 @@ int api_exec ( const char *subsystem, htsmsg_t *args, htsmsg_t **resp );
* Initialise
*/
void api_init ( void );
void api_done ( void );
void api_idnode_init ( void );
void api_input_init ( void );
void api_service_init ( void );
Expand Down
2 changes: 2 additions & 0 deletions src/api/api_idnode.c
Expand Up @@ -170,6 +170,8 @@ api_idnode_load_by_class
if (e)
htsmsg_add_msg(l, NULL, e);
}
free(is->is_array);
free(is);
}
*resp = htsmsg_create_map();
htsmsg_add_msg(*resp, "entries", l);
Expand Down
17 changes: 13 additions & 4 deletions src/avahi.c
Expand Up @@ -54,6 +54,7 @@

static AvahiEntryGroup *group = NULL;
static char *name = NULL;
static AvahiSimplePoll *avahi_asp = NULL;

static void create_services(AvahiClient *c);

Expand Down Expand Up @@ -247,14 +248,13 @@ client_callback(AvahiClient *c, AvahiClientState state, void *userdata)
static void *
avahi_thread(void *aux)
{
AvahiSimplePoll *asp = avahi_simple_poll_new();
const AvahiPoll *ap = avahi_simple_poll_get(asp);

name = avahi_strdup("Tvheadend");

avahi_client_new(ap, AVAHI_CLIENT_NO_FAIL, client_callback, NULL, NULL);

while((avahi_simple_poll_iterate(asp, -1)) != -1) {}
while(avahi_simple_poll_iterate(asp, -1) == 0);

return NULL;

Expand All @@ -264,10 +264,19 @@ avahi_thread(void *aux)
/**
*
*/
pthread_t avahi_tid;

void
avahi_init(void)
{
pthread_t tid;
avahi_asp = avahi_simple_poll_new();
tvhthread_create(&avahi_tid, NULL, avahi_thread, NULL, 0);
}

tvhthread_create(&tid, NULL, avahi_thread, NULL, 1);
void
avahi_done(void)
{
avahi_simple_poll_quit(avahi_asp);
pthread_kill(avahi_tid, SIGTERM);
pthread_join(avahi_tid, NULL);
}
6 changes: 6 additions & 0 deletions src/avahi.h
@@ -1 +1,7 @@
#ifdef CONFIG_AVAHI
void avahi_init(void);
void avahi_done(void);
#else
static inline void avahi_init(void) { }
static inline void avahi_done(void) { }
#endif
56 changes: 45 additions & 11 deletions src/channels.c
Expand Up @@ -48,9 +48,12 @@ struct channel_tag_queue channel_tags;
static dtable_t *channeltags_dtable;

static void channel_tag_init ( void );
static void channel_tag_done ( void );
static channel_tag_t *channel_tag_find(const char *id, int create);
static void channel_tag_mapping_destroy(channel_tag_mapping_t *ctm,
int flags);
static void channel_tag_destroy(channel_tag_t *ct, int delconf);


#define CTM_DESTROY_UPDATE_TAG 0x1
#define CTM_DESTROY_UPDATE_CHANNEL 0x2
Expand All @@ -74,7 +77,7 @@ channel_class_save ( idnode_t *self )
static void
channel_class_delete ( idnode_t *self )
{
channel_delete((channel_t*)self);
channel_delete((channel_t*)self, 1);
}

static const void *
Expand Down Expand Up @@ -540,22 +543,23 @@ channel_create0
}

void
channel_delete ( channel_t *ch )
channel_delete ( channel_t *ch, int delconf )
{
th_subscription_t *s;
channel_tag_mapping_t *ctm;
channel_service_mapping_t *csm;

lock_assert(&global_lock);

tvhinfo("channel", "%s - deleting", channel_get_name(ch));
if (delconf)
tvhinfo("channel", "%s - deleting", channel_get_name(ch));

/* Tags */
while((ctm = LIST_FIRST(&ch->ch_ctms)) != NULL)
channel_tag_mapping_destroy(ctm, CTM_DESTROY_UPDATE_TAG);

/* DVR */
autorec_destroy_by_channel(ch);
autorec_destroy_by_channel(ch, delconf);
dvr_destroy_by_channel(ch);

/* Services */
Expand All @@ -573,7 +577,8 @@ channel_delete ( channel_t *ch )
epg_channel_unlink(ch);

/* Settings */
hts_settings_remove("channel/%s", idnode_uuid_as_str(&ch->ch_id));
if (delconf)
hts_settings_remove("channel/%s", idnode_uuid_as_str(&ch->ch_id));

/* Free memory */
RB_REMOVE(&channels, ch, ch_link);
Expand Down Expand Up @@ -619,6 +624,21 @@ channel_init ( void )
htsmsg_destroy(c);
}

/**
*
*/
void
channel_done ( void )
{
channel_t *ch;

pthread_mutex_lock(&global_lock);
while ((ch = RB_FIRST(&channels)) != NULL)
channel_delete(ch, 0);
pthread_mutex_unlock(&global_lock);
channel_tag_done();
}

/* ***
* Channel tags TODO
*/
Expand Down Expand Up @@ -732,15 +752,17 @@ channel_tag_find(const char *id, int create)
*
*/
static void
channel_tag_destroy(channel_tag_t *ct)
channel_tag_destroy(channel_tag_t *ct, int delconf)
{
channel_tag_mapping_t *ctm;
channel_t *ch;

while((ctm = LIST_FIRST(&ct->ct_ctms)) != NULL) {
ch = ctm->ctm_channel;
channel_tag_mapping_destroy(ctm, CTM_DESTROY_UPDATE_CHANNEL);
channel_save(ch);
if (delconf) {
while((ctm = LIST_FIRST(&ct->ct_ctms)) != NULL) {
ch = ctm->ctm_channel;
channel_tag_mapping_destroy(ctm, CTM_DESTROY_UPDATE_CHANNEL);
channel_save(ch);
}
}

if(ct->ct_enabled && !ct->ct_internal)
Expand Down Expand Up @@ -878,7 +900,7 @@ channel_tag_record_delete(void *opaque, const char *id)

if((ct = channel_tag_find(id, 0)) == NULL)
return -1;
channel_tag_destroy(ct);
channel_tag_destroy(ct, 1);
return 0;
}

Expand Down Expand Up @@ -949,3 +971,15 @@ channel_tag_init ( void )
channeltags_dtable = dtable_create(&channel_tags_dtc, "channeltags", NULL);
dtable_load(channeltags_dtable);
}

static void
channel_tag_done ( void )
{
channel_tag_t *ct;

pthread_mutex_lock(&global_lock);
while ((ct = TAILQ_FIRST(&channel_tags)) != NULL)
channel_tag_destroy(ct, 0);
pthread_mutex_unlock(&global_lock);
dtable_delete("channeltags");
}
3 changes: 2 additions & 1 deletion src/channels.h
Expand Up @@ -120,14 +120,15 @@ typedef struct channel_service_mapping {
extern const idclass_t channel_class;

void channel_init(void);
void channel_done(void);

channel_t *channel_create0
(channel_t *ch, const idclass_t *idc, const char *uuid, htsmsg_t *conf,
const char *name);
#define channel_create(u, c, n)\
channel_create0(calloc(1, sizeof(channel_t)), &channel_class, u, c, n)

void channel_delete(channel_t *ch);
void channel_delete(channel_t *ch, int delconf);

channel_t *channel_find_by_name(const char *name);
#define channel_find_by_uuid(u)\
Expand Down
5 changes: 5 additions & 0 deletions src/config2.c
Expand Up @@ -33,6 +33,11 @@ void config_init ( void )
}
}

void config_done ( void )
{
htsmsg_destroy(config);
}

void config_save ( void )
{
hts_settings_save(config, "config");
Expand Down
1 change: 1 addition & 0 deletions src/config2.h
Expand Up @@ -24,6 +24,7 @@
#include "htsmsg.h"

void config_init ( void );
void config_done ( void );
void config_save ( void );

htsmsg_t *config_get_all ( void );
Expand Down
1 change: 1 addition & 0 deletions src/descrambler.h
Expand Up @@ -77,6 +77,7 @@ typedef enum {
LIST_HEAD(caid_list, caid);

void descrambler_init ( void );
void descrambler_done ( void );
void descrambler_service_start ( struct service *t );
const char *descrambler_caid2name(uint16_t caid);
uint16_t descrambler_name2caid(const char *str);
Expand Down
21 changes: 19 additions & 2 deletions src/descrambler/capmt.c
Expand Up @@ -185,6 +185,8 @@ typedef struct capmt {

struct capmt_service_list capmt_services;

pthread_t capmt_tid;

/* from capmt configuration */
char *capmt_sockfile;
char *capmt_hostname;
Expand Down Expand Up @@ -1114,7 +1116,6 @@ capmt_destroy(capmt_t *capmt)
static capmt_t *
capmt_entry_find(const char *id, int create)
{
pthread_t ptid;
char buf[20];
capmt_t *capmt;
static int tally;
Expand Down Expand Up @@ -1143,7 +1144,7 @@ capmt_entry_find(const char *id, int create)

TAILQ_INSERT_TAIL(&capmts, capmt, capmt_link);

tvhthread_create(&ptid, NULL, capmt_thread, capmt, 1);
tvhthread_create(&capmt->capmt_tid, NULL, capmt_thread, capmt, 1);

return capmt;
}
Expand Down Expand Up @@ -1281,3 +1282,19 @@ capmt_init(void)
dtable_load(dt);
}

void
capmt_done(void)
{
capmt_t *capmt, *n;
pthread_t tid;

for (capmt = TAILQ_FIRST(&capmts); capmt != NULL; capmt = n) {
n = TAILQ_NEXT(capmt, capmt_link);
pthread_mutex_lock(&global_lock);
tid = capmt->capmt_tid;
capmt_destroy(capmt);
pthread_mutex_unlock(&global_lock);
pthread_join(tid, NULL);
}
dtable_delete("capmt");
}
2 changes: 2 additions & 0 deletions src/descrambler/capmt.h
Expand Up @@ -21,6 +21,8 @@

void capmt_init(void);

void capmt_done(void);

void capmt_service_start(struct service *t);

#endif /* CAPMT_H_ */

4 comments on commit c07824a

@BtbN
Copy link
Contributor

@BtbN BtbN commented on c07824a Mar 6, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Starting with this commit, tvheadend crashes on startup for me:
#0 0x0000000000432404 in htsmsg_field_destroy (msg=0x7fcd20, f=0x314144542050584e) at src/htsmsg.c:40
#1 0x000000000043251a in htsmsg_clear (msg=0x7fcd20) at src/htsmsg.c:74
#2 0x0000000000432791 in htsmsg_destroy (msg=0x7fcd20) at src/htsmsg.c:178
#3 0x00000000004923b1 in linuxdvb_adapter_add (path=0x7fffffffd430 "/dev/dvb/adapter0") at src/input/mpegts/linuxdvb/linuxdvb_adapter.c:300
#4 0x0000000000492569 in linuxdvb_adapter_scan () at src/input/mpegts/linuxdvb/linuxdvb_adapter.c:363
#5 0x000000000049268e in linuxdvb_adapter_init () at src/input/mpegts/linuxdvb/linuxdvb_adapter.c:429
#6 0x00000000004918fa in linuxdvb_init (adapter_mask=-1) at src/input/mpegts/linuxdvb/linuxdvb.c:46
#7 0x000000000040763e in main (argc=1, argv=0x7fffffffe488) at src/main.c:770

@nmaclean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a similar issue

Mar 7 06:49:39 server kernel: [418110.554381] tvheadend[17311]: segfault at 0 ip (null) sp 00007fffcd8de598 error 14 in tvheadend[400000+bd000]
Mar 7 06:49:40 server tvheadend[17324]: thread: created thread 139847785441024 [tvhlog_thread / 0x408c40((nil))]
Mar 7 06:49:40 server tvheadend[17324]: thread: created thread 139847777048320 [idnode_thread / 0x40a5b0((nil))]
Mar 7 06:49:40 server tvheadend[17324]: thread: created thread 139847768655616 [fsmonitor / 0x433e10((nil))]
Mar 7 06:49:40 server tvheadend[17324]: thread: created thread 139847557707520 [imagecache_thread / 0x430580((nil))]
Mar 7 06:49:40 server tvheadend[17324]: mpegts: IPTV - added network IPTV Network
Mar 7 06:49:40 server tvheadend[17324]: thread: created thread 139847540922112 [mpegts_input_tabl / 0x453dd0(0xf6d8f0)]
Mar 7 06:49:40 server tvheadend[17324]: thread: created thread 139847532529408 [iptv_input_thread / 0x46e830((nil))]
Mar 7 06:49:40 server tvheadend[17324]: CRASH: Signal: 11 in PRG: tvheadend (3.9.409~g342d0e7) [ada90958fdba3be0354053de1900efdcd6d21e38] CWD: /
Mar 7 06:49:40 server tvheadend[17324]: CRASH: Fault address (nil) (Address not mapped)
Mar 7 06:49:40 server tvheadend[17324]: CRASH: Loaded libraries: /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 /lib/x86_64-linux-gnu/libz.so.1 /usr/lib/x86_64-linux-gnu/libcurl-gnutls.so.4 /usr/lib/x86_64-linux-gnu/libavahi-common.so.3 /usr/lib/x86_64-linux-gnu/libavahi-client.so.3 /usr/lib/x86_64-linux-gnu/libavcodec.so.53 /usr/lib/x86_64-linux-gnu/libavutil.so.51 /usr/lib/x86_64-linux-gnu/libavformat.so.53 /usr/lib/x86_64-linux-gnu/libswscale.so.2 /lib/x86_64-linux-gnu/librt.so.1 /lib/x86_64-linux-gnu/libdl.so.2 /lib/x86_64-linux-gnu/libpthread.so.0 /lib/x86_64-linux-gnu/libm.so.6 /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libidn.so.11 /usr/lib/x86_64-linux-gnu/librtmp.so.0 /lib/x86_64-linux-gnu/libgcrypt.so.11 /usr/lib/x86_64-linux-gnu/libgnutls.so.26 /usr/lib/x86_64-linux-gnu/libgssapi_krb5.so.2 /usr/lib/x86_64-linux-gnu/liblber-2.4.so.2 /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2 /lib/x86_64-linux-gnu/libdbus-1.so.3 /usr/lib/x86_64-linux-gnu/libvpx.so.1 /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2 /usr/lib/x86_64-linux-gnu/libvorbis
Mar 7 06:49:40 server tvheadend[17324]: CRASH: Register dump [23]: 632e6362622e77776c70692f6b752e6f0076742f72657961000000000000000100007fffeaaf16c000007fffeaaf17c0000000000000ffff0000000000f60a1000000000006d1dc000007fffeaaf16c000000000006d1dc00000000000f67b7000000000000001000000000000f67c08000000000000007000007fffeaaf16a80000000000000000000000000001020200000000000000330000000000000014000000000000000efffffffe7ffbfa170000000000000000
Mar 7 06:49:40 server tvheadend[17324]: CRASH: STACKTRACE
Mar 7 06:49:40 server tvheadend[17324]: thread: created thread 139847549314816 [service_saver / 0x41f990((nil))]
Mar 7 06:49:40 server tvheadend[17324]: CRASH: /tmp/tvheadend/src/trap.c:148 0x42c4b9

@jdierkse
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@perexg Adding epggrab_running in while ( epggrab_running && mod->enabled && mod->sock ) { (in module.c) causes epggrabbers that are not internal (like XMLTV) to create a socket, and exit immediately upon startup of tvheadend. Can you fix this?

@perexg
Copy link
Contributor Author

@perexg perexg commented on c07824a Aug 15, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdierkse : Thanks. Fixed in 1dc009a .

Please sign in to comment.