Mon, 12 Aug 2024 00:22:37 +0200
implement keep-alive timeout
--- 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); }