implement keep-alive timeout

Mon, 12 Aug 2024 00:22:37 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 12 Aug 2024 00:22:37 +0200
changeset 543
3335f431a91b
parent 542
1327febf99c4
child 544
27684460629f

implement keep-alive timeout

src/server/daemon/event.c file | annotate | diff | comparison | revisions
src/server/daemon/event.h file | annotate | diff | comparison | revisions
src/server/daemon/event_linux.c file | annotate | diff | comparison | revisions
src/server/daemon/sessionhandler.c file | annotate | diff | comparison | revisions
--- a/src/server/daemon/event.c	Sun Aug 11 18:51:39 2024 +0200
+++ b/src/server/daemon/event.c	Mon Aug 12 00:22:37 2024 +0200
@@ -161,5 +161,22 @@
         t = time(NULL);
     }
     
+    log_ereport(LOG_DEBUG, "eventhandler: check watchlist");
+    
+    EVWatchList *elm = h->watchlist_begin;
+    while(elm) {
+        EVWatchList *next = elm->next;
+        
+        if(elm->expire < t) {
+            ev_watchlist_remove(h, elm);
+            
+            if(elm->destroy) {
+                elm->destroy(h, elm);
+            }
+        }
+        
+        elm = next;
+    }
+    
     
 }
--- a/src/server/daemon/event.h	Sun Aug 11 18:51:39 2024 +0200
+++ b/src/server/daemon/event.h	Mon Aug 12 00:22:37 2024 +0200
@@ -36,8 +36,11 @@
 extern "C" {
 #endif
     
-#define EV_MAX_EVENTS 32
-
+#define EV_MAX_EVENTS    32
+#define EV_IDLE_TIMEOUT  120
+#define EV_IDLE_LOOP_CTN 16
+    
+    
 typedef struct EVHandler {
     EventHandler **instances;
     uint32_t     numins;
@@ -63,7 +66,8 @@
     time_t created;
     time_t expire;
     evwatchlist_destroyfunc destroy;
-    void *data;
+    void *data1;
+    void *data2;
     int intdata;
     EVWatchList *prev;
     EVWatchList *next;
--- a/src/server/daemon/event_linux.c	Sun Aug 11 18:51:39 2024 +0200
+++ b/src/server/daemon/event_linux.c	Mon Aug 12 00:22:37 2024 +0200
@@ -94,14 +94,15 @@
     struct epoll_event events[EV_MAX_EVENTS];
     Event* finished[EV_MAX_EVENTS];
     
+    int loop_ctn = 0;
     for(;;) {
         /* wait for events */
-        int ret = epoll_wait(ep, events, 16, 100000);
+        int ret = epoll_wait(ep, events, 16, EV_IDLE_TIMEOUT * 1000);
         if(ret == -1 && errno != EINTR) {
             log_ereport(LOG_FAILURE, "epoll_wait failed: %s", strerror(errno));
             continue;
         }
-        
+              
         int numfinished = 0;
         ev->base.numret = 0;
         for(int i=0;i<ret;i++) {
@@ -183,6 +184,11 @@
             EVReturn ret = ev->base.fnreturn[i];
             nsapi_saf_return(ret.sn, ret.rq, ret.ret);
         }
+        
+        if(ret == 0 || ++loop_ctn >= EV_IDLE_LOOP_CTN) {
+            watchlist_check(&ev->base, 0);
+            loop_ctn = 0;
+        }
     }
 }
 
@@ -202,7 +208,7 @@
     event->object = (intptr_t)fd;
     event->events = EVENT_POLLIN;
     struct epoll_event epev;
-    epev.events = EPOLLIN | EPOLLET; // input event, edge triggered
+    epev.events = EPOLLIN | EPOLLRDHUP | EPOLLET; // input event, edge triggered
     epev.data.ptr = event;
     return epoll_ctl(ev->ep, EPOLL_CTL_ADD, fd, &epev);
 }
@@ -212,7 +218,7 @@
     event->object = (intptr_t)fd;
     event->events = EVENT_POLLOUT;
     struct epoll_event epev;
-    epev.events = EPOLLOUT | EPOLLET; // input event, edge triggered
+    epev.events = EPOLLOUT | EPOLLRDHUP | EPOLLET; // input event, edge triggered
     epev.data.ptr = event;
     return epoll_ctl(ev->ep, EPOLL_CTL_ADD, fd, &epev);
 }
--- a/src/server/daemon/sessionhandler.c	Sun Aug 11 18:51:39 2024 +0200
+++ b/src/server/daemon/sessionhandler.c	Mon Aug 12 00:22:37 2024 +0200
@@ -497,34 +497,27 @@
         return;
     }
     
-    EVWatchList *keepalive = malloc(sizeof(EVWatchList));
-    if(!keepalive) {
-        free(event);
-        connection_destroy(conn);
-        return;
-    }
-    
-    ZERO(keepalive, sizeof(EVWatchList));
-    keepalive->destroy = evt_keep_alive_destroy;
-    keepalive->data = conn; 
-    
     ZERO(event, sizeof(Event));
     event->fn = evt_keep_alive_enqueue;
     event->finish = ev_free_event; // this will free the event obj at the end
-    event->cookie = keepalive;
+    event->cookie = conn;
     
     EventHandler *ev = ev_instance(((EventSessionHandler*)handler)->eventhandler);
     if(event_send(ev, event)) {
         log_ereport(LOG_FAILURE, "Keep-Alive: ev_send failed");
         connection_destroy(conn);
         free(event);
-        free(keepalive);
     }
 }
 
-int evt_keep_alive_enqueue(EventHandler *h, Event *event) {
-    EVWatchList *keepalive = event->cookie;
-    Connection *conn = keepalive->data;
+int evt_keep_alive_enqueue(EventHandler *h, Event *event) { 
+    Connection *conn = event->cookie;
+    
+    EVWatchList *keepalive = malloc(sizeof(EVWatchList));
+    if(!keepalive) {
+        connection_destroy(conn);
+        return 0;
+    }
     
     Event *ioevent = malloc(sizeof(Event));
     if(!ioevent) {
@@ -535,8 +528,12 @@
     
     // add keepalive object to the eventhandler watchlist
     // the watchlist will check the timeout
+    ZERO(keepalive, sizeof(EVWatchList));
+    keepalive->data1 = conn;
+    keepalive->data2 = ioevent;
+    keepalive->destroy = evt_keep_alive_destroy;
     keepalive->created = time(NULL);
-    keepalive->expire = keepalive->created + 60; // TODO: config
+    keepalive->expire = keepalive->created + 10; // TODO: config
     ev_watchlist_add(h, keepalive);
     
     // wait for input
@@ -557,7 +554,7 @@
 
 int evt_keep_alive_input_event(EventHandler *h, Event *event) {
     EVWatchList *keepalive = event->cookie;
-    Connection *conn = keepalive->data;
+    Connection *conn = keepalive->data1;
     
     // remove connection from the keep-alive list
     ev_watchlist_remove(h, keepalive);
@@ -579,5 +576,15 @@
 }
 
 void evt_keep_alive_destroy(EventHandler *h, EVWatchList *item) {
+    Connection *conn = item->data1;
+    Event *ioevent = item->data2;
+    log_ereport(LOG_DEBUG, "sessionhandler: keep-alive timeout: close connection");
     
+    if(ev_remove_poll(h, conn->fd)) {
+        log_ereport(LOG_FAILURE, "sessionhandler: keep-alive timeout: cannot remove poll");
+    }
+    
+    connection_destroy(conn);
+    free(ioevent);
+    free(item);
 }

mercurial