From 13a46cee36ed4c78276262a60b0bdcc11f49507d Mon Sep 17 00:00:00 2001 From: claudio Date: Fri, 12 Aug 2022 13:24:30 +0000 Subject: [PATCH] Implement slowcgi_timeout() to actually kill the backend bgpctl process. If that succeeds the fcgi session will be terminated the regular way. If it fails close all fds and finish the request. Sending a SIGTERM to a read only bgpctl process should be fine at any point. Also reduce the timeout to 30sec. This is not long enough to dump a full rib but nobody should do that. OK tb@ --- usr.sbin/bgplgd/slowcgi.c | 48 +++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/usr.sbin/bgplgd/slowcgi.c b/usr.sbin/bgplgd/slowcgi.c index 1c6dc378192..02ef8a8d30d 100644 --- a/usr.sbin/bgplgd/slowcgi.c +++ b/usr.sbin/bgplgd/slowcgi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: slowcgi.c,v 1.2 2022/07/08 08:48:56 claudio Exp $ */ +/* $OpenBSD: slowcgi.c,v 1.3 2022/08/12 13:24:30 claudio Exp $ */ /* * Copyright (c) 2020 Claudio Jeker * Copyright (c) 2019 Kristaps Dzonsons @@ -45,7 +45,7 @@ #include "bgplgd.h" #include "http.h" -#define TIMEOUT_DEFAULT 120 +#define TIMEOUT_DEFAULT 30 #define WWW_USER "www" #define BGPLGD_USER "_bgplgd" @@ -106,20 +106,21 @@ struct request { struct event tmo; struct event script_ev; struct event script_err_ev; - int fd; + struct fcgi_response_head response_head; + struct env_head env; uint8_t buf[FCGI_RECORD_SIZE]; size_t buf_pos; size_t buf_len; - struct fcgi_response_head response_head; - struct env_head env; + int fd; int env_count; + int inflight_fds_accounted; pid_t command_pid; int command_status; int script_flags; uint16_t id; uint8_t request_started; uint8_t request_done; - int inflight_fds_accounted; + uint8_t timeout_fired; }; LIST_HEAD(requests_head, request); @@ -220,6 +221,7 @@ usage(void) } struct timeval timeout = { TIMEOUT_DEFAULT, 0 }; +struct timeval kill_timeout = { 5, 0 }; struct slowcgi_proc slowcgi_proc; int debug = 0; int on = 1; @@ -497,7 +499,35 @@ slowcgi_accept(int fd, short events, void *arg) void slowcgi_timeout(int fd, short events, void *arg) { - cleanup_request((struct request*) arg); + struct request *c = arg; + int sig = SIGTERM; + + if (c->script_flags & SCRIPT_DONE) + return; + + ldebug("timeout fired"); + + if (c->timeout_fired) + sig = SIGKILL; + + if (kill(c->command_pid, sig) == -1) { + lwarn("kill child %d after timeout", c->command_pid); + if (event_initialized(&c->script_ev)) { + close(EVENT_FD(&c->script_ev)); + event_del(&c->script_ev); + } + if (event_initialized(&c->script_err_ev)) { + close(EVENT_FD(&c->script_err_ev)); + event_del(&c->script_err_ev); + } + + c->command_status = SIGALRM; + c->script_flags = STDOUT_DONE | STDERR_DONE | SCRIPT_DONE; + create_end_record(c); + } + + if (c->timeout_fired++ == 0) + evtimer_add(&c->tmo, &kill_timeout); } void @@ -517,7 +547,7 @@ slowcgi_sig_handler(int sig, short event, void *arg) if (c->command_pid == pid) break; if (c == NULL) { - lwarnx("caught exit of unknown child %i", pid); + lwarnx("caught exit of unknown child %d", pid); continue; } @@ -527,7 +557,7 @@ slowcgi_sig_handler(int sig, short event, void *arg) c->command_status = WEXITSTATUS(status); ldebug("exit %s%d", - WIFSIGNALED(status) ? "signal" : "", + WIFSIGNALED(status) ? "signal " : "", c->command_status); c->script_flags |= SCRIPT_DONE; -- 2.20.1