--- a/src/server/daemon/event_bsd.c Tue Aug 13 22:14:32 2019 +0200 +++ b/src/server/daemon/event_bsd.c Sat Sep 24 16:26:10 2022 +0200 @@ -67,47 +67,75 @@ timeout.tv_sec = 600; struct kevent events[64]; - struct kevent changes[64]; + struct kevent changes[128]; int numchanges = 0; for(;;) { // wait for events - int nev = kevent(ev->kqueue, changes, numchanges, events, 64, &timeout); + 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; } numchanges = 0; for(int i=0;i<nev;i++) { Event *event = (Event*)events[i].udata; + if(!event) { + if(events[i].flags == 0) { + log_ereport(LOG_WARN, "Unknown kevent (ident=%d)", (int)events[i].ident); + } + // don't warn in case flags is not 0, because socket EOF events + // are triggered even if we apply EV_DELETE in the changelist + // the only way to stop this is to apply the changelist without + // getting new events, but that comes with a performance penalty + + continue; + } + int event_events = event->events; + if(event->fn) { - int ep = event->events; - if(event->fn(ev, event)) { - if(event->events != ep) { - changes[numchanges++].filter = ev_convert2sys_events(ep); + int saved_ev = event->events; + if(!event->fn(ev, event)) { + // ret 0 => remove event + + if(event->finish) { + event->finish(ev, event); } - } else if(event->finish) { - changes[numchanges++].filter = ev_convert2sys_events(ep); - event->finish(ev, event); + + event_events = 0; + } else { + event_events = event->events; + } + + // 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)) { + if((e & EVENT_POLLIN) == EVENT_POLLIN) { + // add + EV_SET(&changes[numchanges++], e_fd, EVFILT_READ, EV_ADD, 0, 0, event); + } else { + // delete + EV_SET(&changes[numchanges++], e_fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + } + } + if((e & EVENT_POLLOUT) != (saved_ev & EVENT_POLLOUT)) { + if((e & EVENT_POLLOUT) == EVENT_POLLOUT) { + // add + EV_SET(&changes[numchanges++], e_fd, EVFILT_WRITE, EV_ADD, 0, 0, event); + } else { + // delete + EV_SET(&changes[numchanges++], e_fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + } + } } } } } } -int ev_convert2sys_events(int events) { - int e = 0; - if((events & EVENT_POLLIN) == EVENT_POLLIN) { - e |= EVFILT_READ; - } - if((events & EVENT_POLLOUT) == EVENT_POLLOUT) { - e |= EVFILT_WRITE; - } - return e; -} - int ev_pollin(EventHandler *h, int fd, Event *event) { event->events = EVENT_POLLIN; struct kevent kev; @@ -122,6 +150,35 @@ return kevent(h->kqueue, &kev, 1, NULL, 0, NULL); } +int ev_remove_poll(EventHandler *h, int fd) { + struct kevent kev; + EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + int r1 = kevent(h->kqueue, &kev, 1, NULL, 0, NULL); + EV_SET(&kev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + int r2 = kevent(h->kqueue, &kev, 1, NULL, 0, NULL); + // in caase r1 or r2 was successful, we return 0 (no error) + return r1 != -1 || r2 != -1 ? 0 : 1; +} + int event_send(EventHandler *h, Event *event) { return 0; } + +// TODO: remove this fake aio +int ev_aioread(int fd, aiocb_s *cb) { + ssize_t result = pread(fd, cb->buf, cb->nbytes, cb->offset); + cb->result = result; + if(result < 0) { + cb->result_errno = errno; + } + return event_send(cb->evhandler, cb->event); +} + +int ev_aiowrite(int fd, aiocb_s *cb) { + ssize_t result = pwrite(fd, cb->buf, cb->nbytes, cb->offset); + cb->result = result; + if(result < 0) { + cb->result_errno = errno; + } + return event_send(cb->evhandler, cb->event); +}