This patch introduces a new function, event_base_free, that releases memory held by a libevent base. Freeing bases is useful for people who want to use dmalloc (or similar tools) to verify that their programs aren't leaking memory, for program subcomponents that wneed to be loaded and unloaded, and so on.
There are a couple potentially controversial aspects: 1. It requires that all events be deleted from the base before it is called. If not, an assertion is raised. (IMO, this is the only sensible behavior, since otherwise we have no good way to free the events' ev_arg field.) 2. It doesn't do anything useful about freeing resources held in signal.c. (Refactoring signal.c to play nicely with multiple bases seems like a separate process.) I've built it and checked it to be superficially vvalid on linux and mac os 10.4; somebody should check out the devpoll.c and win32.c changes. -- Nick Mathewson
? .gdb_history ? Makefile ? Makefile.in ? aclocal.m4 ? autom4te.cache ? config.h ? config.h.in ? config.log ? config.status ? configure ? libtool ? stamp-h1 ? sample/Makefile ? sample/Makefile.in ? test/.gdb_history ? test/Makefile ? test/Makefile.in ? test/regress.gen.c ? test/regress.gen.h Index: devpoll.c =================================================================== RCS file: /cvsroot/levent/libevent/devpoll.c,v retrieving revision 1.7 diff -u -r1.7 devpoll.c --- devpoll.c 29 Mar 2005 07:16:51 -0000 1.7 +++ devpoll.c 27 Mar 2006 00:24:59 -0000 @@ -76,6 +76,7 @@ int devpoll_del (void *, struct event *); int devpoll_recalc (struct event_base *, void *, int); int devpoll_dispatch (struct event_base *, void *, struct timeval *); +void devpoll_dealloc (void *); struct eventop devpollops = { "devpoll", @@ -83,7 +84,8 @@ devpoll_add, devpoll_del, devpoll_recalc, - devpoll_dispatch + devpoll_dispatch, + devpoll_dealloc }; #define NEVENT 32000 @@ -401,3 +403,21 @@ return (0); } + +void +devpoll_dealloc(void *arg) +{ + struct devpollop *devpollop = arg; + + if (devpollop->fds) + free(devpollop->fds); + if (devpollop->events) + free(devpollop->events); + if (devpollop->changes) + free(devpollop->changes); + if (devpollop->dpfd >= 0) + close(devpollop->dpfd); + + memset(devpollop, 0, sizeof(struct devpollop)); + free(devpollop); +} Index: epoll.c =================================================================== RCS file: /cvsroot/levent/libevent/epoll.c,v retrieving revision 1.17 diff -u -r1.17 epoll.c --- epoll.c 12 Nov 2005 19:04:17 -0000 1.17 +++ epoll.c 27 Mar 2006 00:24:59 -0000 @@ -76,6 +76,7 @@ int epoll_del (void *, struct event *); int epoll_recalc (struct event_base *, void *, int); int epoll_dispatch (struct event_base *, void *, struct timeval *); +void epoll_dealloc (void *); struct eventop epollops = { "epoll", @@ -83,7 +84,8 @@ epoll_add, epoll_del, epoll_recalc, - epoll_dispatch + epoll_dispatch, + epoll_dealloc }; #ifdef HAVE_SETFD @@ -349,3 +351,19 @@ return (0); } + +void +epoll_dealloc(void *arg) +{ + struct epollop *epollop = arg; + + if (epollop->fds) + free(epollop->fds); + if (epollop->events) + free(epollop->events); + if (epollop->epfd >= 0) + close(epollop->epfd); + + memset(epollop, 0, sizeof(struct epollop)); + free(epollop); +} Index: event.c =================================================================== RCS file: /cvsroot/levent/libevent/event.c,v retrieving revision 1.45 diff -u -r1.45 event.c --- event.c 17 Dec 2005 20:25:22 -0000 1.45 +++ event.c 27 Mar 2006 00:25:01 -0000 @@ -178,6 +178,32 @@ return (current_base); } +void +event_base_free(struct event_base *base) +{ + int i; + + if (base == NULL && current_base) + base = current_base; + if (base == current_base) + current_base = NULL; + + assert(base); + assert(TAILQ_EMPTY(&base->eventqueue)); + for (i=0; i < base->nactivequeues; ++i) + assert(TAILQ_EMPTY(base->activequeues[i])); + + assert(RB_EMPTY(&base->timetree)); + + for (i = 0; i < base->nactivequeues; ++i) + free(base->activequeues[i]); + free(base->activequeues); + + base->evsel->dealloc(base->evbase); + + free(base); +} + int event_priority_init(int npriorities) { Index: event.h =================================================================== RCS file: /cvsroot/levent/libevent/event.h,v retrieving revision 1.33 diff -u -r1.33 event.h --- event.h 27 Feb 2006 02:27:36 -0000 1.33 +++ event.h 27 Mar 2006 00:25:02 -0000 @@ -135,6 +135,7 @@ int (*del)(void *, struct event *); int (*recalc)(struct event_base *, void *, int); int (*dispatch)(struct event_base *, void *, struct timeval *); + void (*dealloc)(void *); }; #define TIMEOUT_DEFAULT {5, 0} @@ -142,6 +143,7 @@ void *event_init(void); int event_dispatch(void); int event_base_dispatch(struct event_base *); +void event_base_free(struct event_base *); #define _EVENT_LOG_DEBUG 0 #define _EVENT_LOG_MSG 1 Index: kqueue.c =================================================================== RCS file: /cvsroot/levent/libevent/kqueue.c,v retrieving revision 1.27 diff -u -r1.27 kqueue.c --- kqueue.c 17 Dec 2005 20:15:25 -0000 1.27 +++ kqueue.c 27 Mar 2006 00:25:02 -0000 @@ -75,6 +75,7 @@ int kq_recalc (struct event_base *, void *, int); int kq_dispatch (struct event_base *, void *, struct timeval *); int kq_insert (struct kqop *, struct kevent *); +void kq_dealloc (void *); const struct eventop kqops = { "kqueue", @@ -82,7 +83,8 @@ kq_add, kq_del, kq_recalc, - kq_dispatch + kq_dispatch, + kq_dealloc }; void * @@ -394,3 +396,18 @@ return (0); } + +void +kq_dealloc(void *arg) +{ + struct kqop *kqop = arg; + + if (kqop->changes) + free(kqop->changes); + if (kqop->events) + free(kqop->events); + if (kqop->kq) + close(kqop->kq); + memset(kqop, 0, sizeof(struct kqop)); + free(kqop); +} Index: poll.c =================================================================== RCS file: /cvsroot/levent/libevent/poll.c,v retrieving revision 1.19 diff -u -r1.19 poll.c --- poll.c 17 Dec 2005 20:25:22 -0000 1.19 +++ poll.c 27 Mar 2006 00:25:03 -0000 @@ -74,6 +74,7 @@ int poll_del (void *, struct event *); int poll_recalc (struct event_base *, void *, int); int poll_dispatch (struct event_base *, void *, struct timeval *); +void poll_dealloc (void *); struct eventop pollops = { "poll", @@ -81,7 +82,8 @@ poll_add, poll_del, poll_recalc, - poll_dispatch + poll_dispatch, + poll_dealloc }; void * @@ -355,3 +357,21 @@ poll_check_ok(pop); return (0); } + +void +poll_dealloc(void *arg) +{ + struct pollop *pop = arg; + + if (pop->event_set) + free(pop->event_set); + if (pop->event_r_back) + free(pop->event_r_back); + if (pop->event_w_back) + free(pop->event_w_back); + if (pop->idxplus1_by_fd) + free(pop->idxplus1_by_fd); + + memset(pop, 0, sizeof(struct pollop)); + free(pop); +} Index: select.c =================================================================== RCS file: /cvsroot/levent/libevent/select.c,v retrieving revision 1.22 diff -u -r1.22 select.c --- select.c 11 May 2005 04:08:51 -0000 1.22 +++ select.c 27 Mar 2006 00:25:03 -0000 @@ -76,6 +76,7 @@ int select_del (void *, struct event *); int select_recalc (struct event_base *, void *, int); int select_dispatch (struct event_base *, void *, struct timeval *); +void select_dealloc (void *); const struct eventop selectops = { "select", @@ -83,7 +84,8 @@ select_add, select_del, select_recalc, - select_dispatch + select_dispatch, + select_dealloc }; static int select_resize(struct selectop *sop, int fdsz); @@ -350,3 +352,25 @@ check_selectop(sop); return (0); } + +void +select_dealloc(void *arg) +{ + struct selectop *sop = arg; + + if (sop->event_readset_in) + free(sop->event_readset_in); + if (sop->event_writeset_in) + free(sop->event_writeset_in); + if (sop->event_readset_out) + free(sop->event_readset_out); + if (sop->event_writeset_out) + free(sop->event_writeset_out); + if (sop->event_r_by_fd) + free(sop->event_r_by_fd); + if (sop->event_w_by_fd) + free(sop->event_w_by_fd); + + memset(sop, 0, sizeof(struct selectop)); + free(sop); +} Index: WIN32-Code/win32.c =================================================================== RCS file: /cvsroot/levent/libevent/WIN32-Code/win32.c,v retrieving revision 1.4 diff -u -r1.4 win32.c --- WIN32-Code/win32.c 8 Dec 2005 23:05:42 -0000 1.4 +++ WIN32-Code/win32.c 27 Mar 2006 00:25:04 -0000 @@ -81,6 +81,7 @@ int win32_del (void *, struct event *); int win32_recalc (struct event_base *base, void *, int); int win32_dispatch (struct event_base *base, void *, struct timeval *); +void win32_dealloc (void *); struct eventop win32ops = { "win32", @@ -88,7 +89,8 @@ win32_insert, win32_del, win32_recalc, - win32_dispatch + win32_dispatch, + win32_dealloc }; #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET))) @@ -365,6 +367,27 @@ return (0); } +void +win32_dealloc(void *arg) +{ + struct win32op *win32op = arg; + + if (win32op->readset_in) + free(win32op->readset_in); + if (win32op->writeset_in) + free(win32op->writeset_in); + if (win32op->readset_out) + free(win32op->readset_out); + if (win32op->writeset_out) + free(win32op->writeset_out); + if (win32op->exset_out) + free(win32op->exset_out); + if (win32op->events) + free(win32op->events); + + memset(win32op, 0, sizeof(win32op)); + free(win32op); +} static int signal_handler(int sig)
pgpN5uki7XgVt.pgp
Description: PGP signature
_______________________________________________ Libevent-users mailing list Libevent-users@monkey.org http://monkey.org/mailman/listinfo/libevent-users