Protect us (by using a simple refcount) from crash when a fd callback removes another dispatch handle which is about to be served in the same poll loop (thanks valgrind)
This commit is contained in:
parent
b958f02d6b
commit
93e991d06c
1 changed files with 26 additions and 1 deletions
27
dispatch.c
27
dispatch.c
|
@ -36,6 +36,7 @@ typedef struct epoll_entry {
|
|||
void *opaque;
|
||||
struct epoll_event event;
|
||||
int fd;
|
||||
int refcnt;
|
||||
} epoll_entry_t;
|
||||
|
||||
|
||||
|
@ -148,6 +149,7 @@ dispatch_addfd(int fd, void (*callback)(int events, void *opaque, int fd),
|
|||
e->fd = fd;
|
||||
e->event.events = EPOLLERR | EPOLLHUP;
|
||||
e->event.data.ptr = e;
|
||||
e->refcnt = 1;
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, e->fd, &e->event);
|
||||
dispatch_set(e, flags);
|
||||
return e;
|
||||
|
@ -183,6 +185,14 @@ dispatch_clr(void *handle, int flags)
|
|||
epoll_ctl(epoll_fd, EPOLL_CTL_MOD, e->fd, &e->event);
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_deref(struct epoll_entry *e)
|
||||
{
|
||||
if(e->refcnt > 1)
|
||||
e->refcnt--;
|
||||
else
|
||||
free(e);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
|
@ -191,7 +201,10 @@ dispatch_delfd(void *handle)
|
|||
struct epoll_entry *e = handle;
|
||||
int fd = e->fd;
|
||||
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &e->event);
|
||||
free(e);
|
||||
|
||||
e->callback = NULL;
|
||||
e->opaque = NULL;
|
||||
dispatch_deref(e);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -217,6 +230,13 @@ dispatcher(void)
|
|||
|
||||
for(i = 0; i < n; i++) {
|
||||
e = events[i].data.ptr;
|
||||
e->refcnt++;
|
||||
}
|
||||
|
||||
for(i = 0; i < n; i++) {
|
||||
e = events[i].data.ptr;
|
||||
if(e->callback == NULL)
|
||||
continue; /* poll entry has been free'd during loop */
|
||||
|
||||
e->callback(
|
||||
((events[i].events & (EPOLLERR | EPOLLHUP)) ?
|
||||
|
@ -231,5 +251,10 @@ dispatcher(void)
|
|||
e->opaque, e->fd);
|
||||
}
|
||||
|
||||
for(i = 0; i < n; i++) {
|
||||
e = events[i].data.ptr;
|
||||
dispatch_deref(e);
|
||||
}
|
||||
|
||||
stimer_dispatch(dispatch_clock);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue