diff --git a/src/iface.c b/src/iface.c index 3ebebee..6c8bfd6 100644 --- a/src/iface.c +++ b/src/iface.c @@ -962,7 +962,7 @@ static void delete_group_cb(int timeout, void *arg) ifi = config_find_iface(cbk->ifindex); if (!ifi) - goto done; + return; logit(LOG_DEBUG, 0, "Group membership timeout for %s on %s", inet_fmt(cbk->g->al_addr, s1, sizeof(s1)), ifi->ifi_name); @@ -977,8 +977,6 @@ static void delete_group_cb(int timeout, void *arg) TAILQ_REMOVE(&ifi->ifi_groups, g, al_link); free(g); - done: - free(cbk); } /* @@ -987,7 +985,9 @@ static void delete_group_cb(int timeout, void *arg) static int delete_group_timer(int ifindex, struct listaddr *g, int tmo) { cbk_t *cbk; + int tid; + /* cbk is freed as a side effect of pev_timer_del (via the deletion cb) */ cbk = calloc(1, sizeof(cbk_t)); if (!cbk) { logit(LOG_ERR, errno, "%s(): Failed allocating memory", __func__); @@ -1000,7 +1000,10 @@ static int delete_group_timer(int ifindex, struct listaddr *g, int tmo) /* Record mtime for IPC "show igmp" */ // g->al_mtime = virtual_time; - return pev_timer_add(tmo * 1000000, 0, delete_group_cb, cbk); + tid = pev_timer_add(tmo * 1000000, 0, delete_group_cb, cbk); + pev_timer_set_cb_del(tid, free); + + return tid; } /* diff --git a/src/pev.c b/src/pev.c index 1aaa28a..e1b7298 100644 --- a/src/pev.c +++ b/src/pev.c @@ -35,6 +35,7 @@ struct pev { }; void (*cb)(int, void *); + void (*cb_del)(void *); void *arg; }; @@ -97,6 +98,21 @@ int pev_sig_del(int id) return pev_sock_del(id); } +int pev_sig_set_cb_del(int id, void (*cb)(void *)) +{ + struct pev *entry; + + entry = pev_find(PEV_SIG, id); + if (!entry) { + errno = ENOENT; + return -1; + } + + entry->cb_del = cb; + + return 0; +} + /******************************* SOCKETS ******************************/ static int nfds(void) @@ -157,6 +173,9 @@ int pev_sock_del(int id) entry->active = 0; sig_handler(0); + if (entry->cb_del) + entry->cb_del(entry->arg); + return 0; } } @@ -200,6 +219,22 @@ int pev_sock_close(int sd) return 0; } +int pev_sock_set_cb_del(int id, void (*cb)(void *)) +{ + struct pev *entry; + + for (entry = pl; entry; entry = entry->next) { + if (entry->id == id) { + entry->cb_del = cb; + + return 0; + } + } + + errno = ENOENT; + return -1; +} + /******************************* TIMERS *******************************/ static struct pev *timer_ffs(void) @@ -396,6 +431,11 @@ int pev_timer_get(int id) return -1; } +int pev_timer_set_cb_del(int id, void (*cb)(void *)) +{ + return pev_sock_set_cb_del(id, cb); +} + /******************************* GENERIC ******************************/ static struct pev *pev_new(int type, void (*cb)(int, void *), void *arg) diff --git a/src/pev.h b/src/pev.h index 314d381..ad4589b 100644 --- a/src/pev.h +++ b/src/pev.h @@ -33,6 +33,12 @@ int pev_run (void); int pev_sig_add (int signo, void (*cb)(int, void *), void *arg); int pev_sig_del (int id); +/* + * Destructor callback, called when deleting a signal event (pev_sig_del). + * Useful for deallocating heap allocated arg data. + */ +int pev_sig_set_cb_del (int id, void (*cb)(void *)); + /* * Socket or file descriptor callback by sd/fd, only one callback per * descriptor. API changes to CLOEXEC and NONBLOCK. Delete by id @@ -48,6 +54,12 @@ int pev_sock_del (int id); int pev_sock_open (int domain, int type, int proto, void (*cb)(int, void *), void *arg); int pev_sock_close (int id); +/* + * Destructor callback, called when deleting a socket event (pev_sock_del or + * pev_sock_close). Useful for deallocating heap allocated arg data. + */ +int pev_sock_set_cb_del (int id, void (*cb)(void *)); + /* * Periodic timers use SIGALRM via setitimer() API, may affect use of * sleep(), usleep(), and alarm() APIs. See your respective OS for @@ -80,4 +92,10 @@ int pev_timer_del (int id); int pev_timer_set (int id, int timeout); int pev_timer_get (int id); +/* + * Destructor callback, called when deleting a timer (pev_timer_del). + * Useful for deallocating heap allocated arg data. + */ +int pev_timer_set_cb_del (int id, void (*cb)(void *)); + #endif /* PEV_H_ */