src/server/daemon/event_bsd.c

changeset 385
a1f4cb076d2f
parent 342
ebd1e67c3d5f
child 433
39fe86ae4db0
--- 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);
+}

mercurial