Thu, 03 Dec 2020 12:38:46 +0100
fix wrong kqueue usage: split ws events into multiple kevent filters
src/server/daemon/event_bsd.c | file | annotate | diff | comparison | revisions |
--- a/src/server/daemon/event_bsd.c Thu Dec 03 11:47:49 2020 +0100 +++ b/src/server/daemon/event_bsd.c Thu Dec 03 12:38:46 2020 +0100 @@ -67,7 +67,7 @@ timeout.tv_sec = 600; struct kevent events[64]; - struct kevent changes[64]; + struct kevent changes[128]; int numchanges = 0; for(;;) { @@ -75,7 +75,7 @@ int nev = kevent(ev->kqueue, changes, numchanges, events, 64, &timeout); if(nev == -1) { // TODO: check for error - perror("kevent"); + log_ereport(LOG_FAILURE, "kevent: %s", strerror(errno)); continue; } @@ -88,25 +88,29 @@ } if(event->fn) { - u_short kev_flag = 0; int saved_ev = event->events; if(!event->fn(ev, event)) { // ret 0 => remove event - kev_flag = EV_DELETE; + if(event->finish) { event->finish(ev, event); } - } else if(saved_ev != event->events) { - // events changed - kev_flag = EV_ADD; - events[i].filter = ev_convert2sys_events(event->events); + + event->events = 0; } - if(kev_flag) { - // copy current event to changelist - changes[numchanges] = events[i]; - changes[numchanges].flags = kev_flag; - numchanges++; + // if events have changed, we need to add/remove filters + if(saved_ev != event->events) { + int e = event->events; + int e_fd = events[i].ident; + if((e & EVENT_POLLIN) != (saved_ev & EVENT_POLLIN)) { + int f = (e & EVENT_POLLIN) == EVENT_POLLIN ? EV_ADD : EV_DELETE; + EV_SET(&changes[numchanges++], e_fd, EVFILT_READ, f, 0, 0, event); + } + if((e & EVENT_POLLOUT) != (saved_ev & EVENT_POLLOUT)) { + int f = (e & EVENT_POLLOUT) == EVENT_POLLOUT ? EV_ADD : EV_DELETE; + EV_SET(&changes[numchanges++], e_fd, EVFILT_WRITE, f, 0, 0, event); + } } } }