src/server/daemon/event_linux.c

changeset 133
87b405d61f64
parent 126
631aaa01b2b5
child 152
8b85c5face66
--- a/src/server/daemon/event_linux.c	Tue Dec 27 14:02:28 2016 +0100
+++ b/src/server/daemon/event_linux.c	Tue Dec 27 17:19:00 2016 +0100
@@ -97,24 +97,49 @@
         /* wait for events */
         int ret = epoll_wait(ep, events, 16, 100000);
         if(ret == -1 && errno != EINTR) {
-            /* TODO: check for error */
-            perror("epoll_wait");
+            log_ereport(LOG_FAILURE, "epoll_wait failed: %s", strerror(errno));
             continue;
         }
         
         for(int i=0;i<ret;i++) {
             event_t *event = events[i].data.ptr;
             if(event->fn) {
+                int saved_ev = event->poll;
                 if(!event->fn(ev, event)) {
                     // event fn returned 0 -> remove event from epoll
                     if(epoll_ctl(ep, EPOLL_CTL_DEL, event->object, NULL)) {
-                        perror("epoll_ctl");
+                        log_ereport(
+                                LOG_FAILURE,
+                                "epoll_ctl failed: %s",
+                                strerror(errno));
                     }
                     
                     // if set, execute event->finish
                     if(event->finish) {
                         event->finish(ev, event);
                     }
+                } else {
+                    if(saved_ev != event->poll) {
+                        // event type changed
+                        struct epoll_event epev;
+                        epev.events = EPOLLET;
+                        epev.data.ptr = event;
+                        
+                        // adjust epoll events
+                        if((event->poll & EVENT_POLLIN) == EVENT_POLLIN) {
+                            epev.events |= EPOLLIN;
+                        }
+                        if((event->poll & EVENT_POLLOUT) == EVENT_POLLOUT) {
+                            epev.events |= EPOLLOUT;
+                        }
+                        
+                        if(epoll_ctl(ep, EPOLL_CTL_MOD, event->object, NULL)) {
+                            log_ereport(
+                                    LOG_FAILURE,
+                                    "epoll_wait failed: %s",
+                                    strerror(errno));
+                        }
+                    }
                 }
             }
         }
@@ -136,23 +161,25 @@
 
 int ev_pollin(event_handler_t *h, int fd, event_t *event) {
     event->object = (intptr_t)fd;
+    event->poll = EVENT_POLLIN;
     struct epoll_event epev;
-    epev.events = EPOLLIN | EPOLLET; /* input event, edge triggered */
+    epev.events = EPOLLIN | EPOLLET; // input event, edge triggered
     epev.data.ptr = event;
     return epoll_ctl(ev_get_port(h), EPOLL_CTL_ADD, fd, &epev);
 }
 
 int ev_pollout(event_handler_t *h, int fd, event_t *event) {
     event->object = (intptr_t)fd;
+    event->poll = EVENT_POLLOUT;
     struct epoll_event epev;
-    epev.events = EPOLLOUT | EPOLLET; /* input event, edge triggered */
+    epev.events = EPOLLOUT | EPOLLET; // input event, edge triggered
     epev.data.ptr = event;
     return epoll_ctl(ev_get_port(h), EPOLL_CTL_ADD, fd, &epev);
 }
 
 int evt_send(event_handler_t *h, event_t *event) {
     event->object = 0;
-    // TODO: implement using threadpool
+    // TODO: implement using threadpool or eventfd
     fprintf(stderr, "Warning: evt_send not implemented\n");
     return 0;
 }

mercurial