diff options
author | Eric Wong <e@80x24.org> | 2013-12-27 23:02:48 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-12-27 23:03:53 +0000 |
commit | 45ce6646ab7cc62ad30ec0bf9c68719f9c467866 (patch) | |
tree | 809dc13cfe7b82875a52a6761a4834475fe32c86 /ext/sleepy_penguin/epoll.c | |
parent | a00b3766fa4c498a65f5742e161a382717db3041 (diff) | |
download | sleepy_penguin-45ce6646ab7cc62ad30ec0bf9c68719f9c467866.tar.gz |
Storing heap-allocated memory in __thread is not feasible for a library since it provides no automatic resource de-allocation. This oversight caused rare applications which use short-lived threads for epoll_wait, kevent, or inotify read to leak memory over time. So we refactor everything to use pthread_* thread-local storage APIs instead. While we're at it, we can safely use a common, generic buffer for inotify, epoll, and kevent to avoid running into PTHREAD_KEYS_MAX limitations. These leaks only affected sleepy_penguin v3.2.0 and later, and only applications which use short-lived threads to call epoll_wait, kevent and inotify read.
Diffstat (limited to 'ext/sleepy_penguin/epoll.c')
-rw-r--r-- | ext/sleepy_penguin/epoll.c | 17 |
1 files changed, 2 insertions, 15 deletions
diff --git a/ext/sleepy_penguin/epoll.c b/ext/sleepy_penguin/epoll.c index 5e5cb20..423ed69 100644 --- a/ext/sleepy_penguin/epoll.c +++ b/ext/sleepy_penguin/epoll.c @@ -1,7 +1,6 @@ #include "sleepy_penguin.h" #ifdef HAVE_SYS_EPOLL_H #include <sys/epoll.h> -#include <unistd.h> #include <time.h> #include "missing_clock_gettime.h" #include "missing_epoll.h" @@ -52,10 +51,8 @@ static int ep_fd_check(struct ep_per_thread *ept) static struct ep_per_thread *ept_get(VALUE self, int maxevents) { - static __thread struct ep_per_thread *ept; + struct ep_per_thread *ept; size_t size; - int err; - void *ptr; /* error check here to prevent OOM from posix_memalign */ if (maxevents <= 0) { @@ -63,21 +60,11 @@ static struct ep_per_thread *ept_get(VALUE self, int maxevents) rb_sys_fail("epoll_wait maxevents <= 0"); } - if (ept && ept->capa >= maxevents) - goto out; - size = sizeof(struct ep_per_thread) + sizeof(struct epoll_event) * maxevents; - free(ept); /* free(NULL) is POSIX and works on glibc */ - err = posix_memalign(&ptr, rb_sp_l1_cache_line_size, size); - if (err) { - errno = err; - rb_memerror(); - } - ept = ptr; + ept = rb_sp_gettlsbuf(&size); ept->capa = maxevents; -out: ept->maxevents = maxevents; ept->io = self; ept->fd = rb_sp_fileno(ept->io); |