Sat, 24 Aug 2024 12:13:01 +0200
add request timeout handler
--- a/src/server/daemon/httplistener.c Tue Aug 20 12:34:32 2024 +0200 +++ b/src/server/daemon/httplistener.c Sat Aug 24 12:13:01 2024 +0200 @@ -747,7 +747,7 @@ return 1; } - int keepidle = 60; + int keepidle = 240; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle))) { log_ereport(LOG_FAILURE, "listener: cannot set TCP_KEEPIDLE to value %d: %s", keepidle, strerror(errno)); return 1;
--- a/src/server/daemon/sessionhandler.c Tue Aug 20 12:34:32 2024 +0200 +++ b/src/server/daemon/sessionhandler.c Sat Aug 24 12:13:01 2024 +0200 @@ -42,6 +42,8 @@ struct EventHttpIO { HTTPRequest *request; HttpParser *parser; + EVWatchList watch; + Event *io_event; int error; }; @@ -221,6 +223,26 @@ return (SessionHandler*)handler; } +void evt_request_timeout(EventHandler *h, EVWatchList *item) { + log_ereport(LOG_VERBOSE, "sessionhandler: request timeout"); + item->intdata = 0; + + EventHttpIO *io = item->data1; + io->error = 4; + + if(ev_remove_poll(h, io->request->connection->fd)) { + log_ereport(LOG_FAILURE, "sessionhandler: request timeout: cannot remove poll"); + } + evt_request_error(h, io->io_event); +} + +int evt_add_request_timeout(EventHandler *h, Event *event) { + EventHttpIO *io = event->cookie; + io->watch.intdata = 1; + ev_watchlist_add(h, &io->watch); + return 0; +} + void evt_enq_conn(SessionHandler *handler, Connection *conn) { Event *event = malloc(sizeof(Event)); if(!event) { @@ -245,6 +267,7 @@ event->fn = conn->ssl && !conn->ssl_accepted ? evt_request_ssl_accept : evt_request_input; event->finish = evt_request_finish; event->cookie = io; + io->io_event = event; EventHandler *ev = ev_instance(((EventSessionHandler*)handler)->eventhandler); @@ -252,6 +275,26 @@ // TODO: ev_pollin should log, intercept some errors here log_ereport(LOG_FAILURE, "Cannot enqueue connection"); evt_request_error(ev, event); + } else { + // add request timeout + io->watch.created = time(NULL); + io->watch.expire = io->watch.created + 240; // TODO: config + io->watch.destroy = evt_request_timeout; + io->watch.data1 = io; + + Event *add_timeout = malloc(sizeof(Event)); + if(add_timeout) { + add_timeout->cookie = io; + add_timeout->fn = evt_add_request_timeout; + add_timeout->finish = ev_free_event; + add_timeout->error = 0; + if(event_send(ev, add_timeout)) { + log_ereport(LOG_FAILURE, "Cannot add request timeout: event_send failed"); + } + } else { + // not an error that breaks everything, a log message is enough + log_ereport(LOG_FAILURE, "Cannot add request timeout: OOM"); + } } } @@ -316,6 +359,7 @@ io->request = request; io->parser = parser; io->error = 0; + ZERO(&io->watch, sizeof(EVWatchList)); return io; } @@ -446,6 +490,11 @@ EventHttpIO *io = event->cookie; HttpParser *parser = io->parser; HTTPRequest *request = io->request; + + // remove timeout + if(io->watch.intdata) { + ev_watchlist_remove(h, &io->watch); + } int r = handle_request(request, NULL, h); if(r != 0) { @@ -478,6 +527,11 @@ log_ereport(LOG_VERBOSE, "sessionhandler http io error: %d fd: %d", io->error, request->connection->fd); } + // remove timeout + if(io->watch.intdata) { + ev_watchlist_remove(h, &io->watch); + } + free(request->netbuf->inbuf); free(request->netbuf);
--- a/src/server/daemon/sessionhandler.h Tue Aug 20 12:34:32 2024 +0200 +++ b/src/server/daemon/sessionhandler.h Sat Aug 24 12:13:01 2024 +0200 @@ -156,6 +156,10 @@ SessionHandler* create_event_session_handler(pool_handle_t *pool); +void evt_request_timeout(EventHandler *h, EVWatchList *item); + +int evt_add_request_timeout(EventHandler *h, Event *event); + void evt_enq_conn(SessionHandler *handler, Connection *conn); EventHttpIO* evt_req_init(SessionHandler *handler, Connection *conn);