After all this slowcgi timeout fixing, here a similar thing for bgplgd(8).
If the timeout fires, kill the bgpctl command first with SIGTERM then with
SIGKILL. If the kill fails, close and cleanup the connection.
I also reduced the timeout to a more reasonable 30sec. Lets see how that
goes. This will abort full show rib commands but nobody should use those
anyway.

-- 
:wq Claudio

Index: slowcgi.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgplgd/slowcgi.c,v
retrieving revision 1.2
diff -u -p -r1.2 slowcgi.c
--- slowcgi.c   8 Jul 2022 08:48:56 -0000       1.2
+++ slowcgi.c   12 Aug 2022 10:50:57 -0000
@@ -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, voi
 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 %i 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
@@ -527,7 +557,7 @@ slowcgi_sig_handler(int sig, short event
                                c->command_status = WEXITSTATUS(status);
 
                        ldebug("exit %s%d",
-                           WIFSIGNALED(status) ? "signal" : "",
+                           WIFSIGNALED(status) ? "signal " : "",
                            c->command_status);
 
                        c->script_flags |= SCRIPT_DONE;

Reply via email to