Implement slowcgi_timeout() to actually kill the backend bgpctl process.
authorclaudio <claudio@openbsd.org>
Fri, 12 Aug 2022 13:24:30 +0000 (13:24 +0000)
committerclaudio <claudio@openbsd.org>
Fri, 12 Aug 2022 13:24:30 +0000 (13:24 +0000)
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

index 1c6dc37..02ef8a8 100644 (file)
@@ -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 <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -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;