diff --git a/lib/poller.c b/lib/poller.c index 757a96607..3ac209646 100644 --- a/lib/poller.c +++ b/lib/poller.c @@ -32,8 +32,7 @@ struct poller_item_int { struct poller { int fd; mutex_t lock; - struct poller_item_int **items; - unsigned int items_size; + GPtrArray *items; }; struct poller_map { @@ -96,6 +95,11 @@ void poller_map_free(struct poller_map **map) { *map = NULL; } +static void poller_free_item(struct poller_item_int *ele) { + if (ele) + obj_put(ele); +} + struct poller *poller_new(void) { struct poller *p; @@ -104,6 +108,7 @@ struct poller *poller_new(void) { p->fd = epoll_create1(0); if (p->fd == -1) goto err; + p->items = g_ptr_array_new_full(1024, (GDestroyNotify) poller_free_item); return p; @@ -114,18 +119,15 @@ err: void poller_free(struct poller **pp) { struct poller *p = *pp; - for (unsigned int i = 0; i < p->items_size; i++) { - struct poller_item_int *ip = p->items[i]; - if (!ip) - continue; - p->items[i] = NULL; - obj_put(ip); - } + + // prevent recursion into poller_del_item from item's free functions + GPtrArray *arr = p->items; + p->items = NULL; + g_ptr_array_free(arr, TRUE); // calls the clear function to release references + if (p->fd != -1) close(p->fd); p->fd = -1; - if (p->items) - free(p->items); g_slice_free1(sizeof(*p), p); *pp = NULL; } @@ -148,7 +150,6 @@ static void poller_item_free(void *p) { int poller_add_item(struct poller *p, struct poller_item *i) { struct poller_item_int *ip; - unsigned int u; struct epoll_event e; if (!p) @@ -166,7 +167,7 @@ int poller_add_item(struct poller *p, struct poller_item *i) { LOCK(&p->lock); - if (i->fd < p->items_size && p->items[i->fd]) + if (i->fd < p->items->len && p->items->pdata[i->fd]) return -1; ZERO(e); @@ -175,17 +176,13 @@ int poller_add_item(struct poller *p, struct poller_item *i) { if (epoll_ctl(p->fd, EPOLL_CTL_ADD, i->fd, &e)) return -1; - if (i->fd >= p->items_size) { - u = p->items_size; - p->items_size = i->fd + 1; - p->items = realloc(p->items, sizeof(*p->items) * p->items_size); - memset(p->items + u, 0, sizeof(*p->items) * (p->items_size - u - 1)); - } + if (i->fd >= p->items->len) + g_ptr_array_set_size(p->items, i->fd + 1); ip = obj_alloc0("poller_item_int", sizeof(*ip), poller_item_free); memcpy(&ip->item, i, sizeof(*i)); obj_hold_o(ip->item.obj); /* new ref in *ip */ - p->items[i->fd] = obj_get(ip); + p->items->pdata[i->fd] = obj_get(ip); } // unlock @@ -205,15 +202,17 @@ int poller_del_item(struct poller *p, int fd) { LOCK(&p->lock); - if (fd >= p->items_size) + if (!p->items) // can happen during shutdown/free only + return -1; + if (fd >= p->items->len) return -1; - if (!p->items || !(it = p->items[fd])) + if (!(it = p->items->pdata[fd])) return -1; if (epoll_ctl(p->fd, EPOLL_CTL_DEL, fd, NULL)) return -1; - p->items[fd] = NULL; /* stealing the ref */ + p->items->pdata[fd] = NULL; /* stealing the ref */ } // unlock @@ -253,7 +252,7 @@ static int poller_poll(struct poller *p, int timeout) { if (ev->data.fd < 0) continue; - it = (ev->data.fd < p->items_size) ? p->items[ev->data.fd] : NULL; + it = (ev->data.fd < p->items->len) ? p->items->pdata[ev->data.fd] : NULL; if (!it) continue; @@ -310,17 +309,18 @@ void poller_blocked(struct poller *p, void *fdp) { LOCK(&p->lock); - if (fd >= p->items_size) + if (fd >= p->items->len) return; - if (!p->items || !p->items[fd]) + struct poller_item_int *it; + if (!(it = p->items->pdata[fd])) return; - if (!p->items[fd]->item.writeable) + if (!it->item.writeable) return; - p->items[fd]->blocked = 1; + it->blocked = 1; ZERO(e); - e.events = epoll_events(NULL, p->items[fd]); + e.events = epoll_events(NULL, it); e.data.fd = fd; epoll_ctl(p->fd, EPOLL_CTL_MOD, fd, &e); } @@ -332,15 +332,16 @@ void poller_error(struct poller *p, void *fdp) { LOCK(&p->lock); - if (fd >= p->items_size) + if (fd >= p->items->len) return; - if (!p->items || !p->items[fd]) + struct poller_item_int *it; + if (!(it = p->items->pdata[fd])) return; - if (!p->items[fd]->item.writeable) + if (!it->item.writeable) return; - p->items[fd]->error = 1; - p->items[fd]->blocked = 1; + it->error = 1; + it->blocked = 1; } int poller_isblocked(struct poller *p, void *fdp) { @@ -353,14 +354,15 @@ int poller_isblocked(struct poller *p, void *fdp) { LOCK(&p->lock); ret = -1; - if (fd >= p->items_size) + if (fd >= p->items->len) goto out; - if (!p->items || !p->items[fd]) + struct poller_item_int *it; + if (!(it = p->items->pdata[fd])) goto out; - if (!p->items[fd]->item.writeable) + if (!it->item.writeable) goto out; - ret = p->items[fd]->blocked ? 1 : 0; + ret = it->blocked ? 1 : 0; out: return ret;