]> git.ipfire.org Git - pakfire.git/commitdiff
jail: Move the timer into the event loop
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 5 Oct 2024 17:27:16 +0000 (17:27 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 5 Oct 2024 17:27:16 +0000 (17:27 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/jail.c

index a4a0499d6e29ac1a1e5637e669d5484db3cbdfe4..dfc50278fdf8e69dcebf94cd25b0341b6bfd6d6e 100644 (file)
@@ -35,7 +35,6 @@
 #include <sys/personality.h>
 #include <sys/prctl.h>
 #include <sys/resource.h>
-#include <sys/timerfd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <termios.h>
@@ -133,7 +132,7 @@ struct pakfire_jail {
        int nice;
 
        // Timeout
-       struct itimerspec timeout;
+       uint64_t timeout;
 
        // CGroup
        struct pakfire_cgroup* cgroup;
@@ -189,6 +188,9 @@ struct pakfire_jail_exec {
 #endif /* ENABLE_DEBUG */
        } log;
 
+       // Timeout
+       sd_event_source* timeout;
+
        struct pakfire_cgroup* cgroup;
        struct pakfire_cgroup_stats cgroup_stats;
 
@@ -478,7 +480,7 @@ PAKFIRE_EXPORT int pakfire_jail_import_env(struct pakfire_jail* jail, const char
 PAKFIRE_EXPORT int pakfire_jail_set_timeout(
                struct pakfire_jail* jail, unsigned int timeout) {
        // Store value
-       jail->timeout.it_value.tv_sec = timeout;
+       jail->timeout = timeout;
 
        if (timeout > 0)
                CTX_DEBUG(jail->ctx, "Timeout set to %u second(s)\n", timeout);
@@ -488,36 +490,6 @@ PAKFIRE_EXPORT int pakfire_jail_set_timeout(
        return 0;
 }
 
-static int pakfire_jail_create_timer(struct pakfire_jail* jail) {
-       int r;
-
-       // Nothing to do if no timeout has been set
-       if (!jail->timeout.it_value.tv_sec)
-               return -1;
-
-       // Create a new timer
-       const int fd = timerfd_create(CLOCK_MONOTONIC, 0);
-       if (fd < 0) {
-               CTX_ERROR(jail->ctx, "Could not create timer: %m\n");
-               goto ERROR;
-       }
-
-       // Arm timer
-       r = timerfd_settime(fd, 0, &jail->timeout, NULL);
-       if (r) {
-               CTX_ERROR(jail->ctx, "Could not arm timer: %m\n");
-               goto ERROR;
-       }
-
-       return fd;
-
-ERROR:
-       if (fd >= 0)
-               close(fd);
-
-       return -1;
-}
-
 /*
        Standard Input
 */
@@ -1125,23 +1097,16 @@ static int pakfire_jail_forward_pty(struct pakfire_jail* jail, struct pakfire_ja
 static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec* ctx) {
        int epollfd = -1;
        struct epoll_event events[EPOLL_MAX_EVENTS];
-       char garbage[8];
        int r = 0;
 
        // Fetch the UNIX domain socket
        const int socket_recv = pakfire_jail_get_pipe_to_read(jail, &ctx->socket);
 
-       // Timer
-       const int timerfd = pakfire_jail_create_timer(jail);
-
        // Make a list of all file descriptors we are interested in
        const struct pakfire_wait_fds {
                const int fd;
                const int events;
        } fds[] = {
-               // Timer
-               { timerfd, EPOLLIN },
-
                // UNIX Domain Socket
                { socket_recv, EPOLLIN },
 
@@ -1228,32 +1193,6 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec
                                        goto ERROR;
                                }
 
-                       // Handle timer events
-                       } else if (timerfd == fd) {
-                               if (e & EPOLLIN) {
-                                       CTX_DEBUG(jail->ctx, "Timer event received\n");
-
-                                       // Disarm the timer
-                                       r = read(timerfd, garbage, sizeof(garbage));
-                                       if (r < 1) {
-                                               CTX_ERROR(jail->ctx, "Could not disarm timer: %m\n");
-                                               r = 1;
-                                               goto ERROR;
-                                       }
-
-                                       // Terminate the process if it hasn't already ended
-                                       if (!ended) {
-                                               CTX_DEBUG(jail->ctx, "Terminating process...\n");
-
-                                               // Send SIGTERM to the process
-                                               r = pidfd_send_signal(ctx->pidfd, SIGKILL, NULL, 0);
-                                               if (r) {
-                                                       CTX_ERROR(jail->ctx, "Could not kill process: %m\n");
-                                                       goto ERROR;
-                                               }
-                                       }
-                               }
-
                        // Handle socket messages
                        } else if (socket_recv == fd) {
                                if (e & EPOLLIN) {
@@ -1293,8 +1232,6 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec
 ERROR:
        if (epollfd >= 0)
                close(epollfd);
-       if (timerfd >= 0)
-               close(timerfd);
 
        // Restore any changed terminal attributes
        if (ctx->pty.stdin.fd >= 0)
@@ -1844,6 +1781,27 @@ static int pakfire_jail_wait_for_signal(struct pakfire_jail* jail, int fd) {
        return r;
 }
 
+/*
+       Called when the timer has expired.
+*/
+static int pakfire_jail_timer(sd_event_source* s, uint64_t usec, void* data) {
+       struct pakfire_jail_exec* ctx = data;
+       struct pakfire_jail* jail = ctx->jail;
+       int r;
+
+       CTX_DEBUG(jail->ctx, "Timer has fired...\n");
+
+       // Send SIGTERM to the process
+       r = pidfd_send_signal(ctx->pidfd, SIGTERM, NULL, 0);
+       if (r)
+               CTX_ERROR(jail->ctx, "Could not send SIGTERM to the process: %m\n");
+
+       return r;
+}
+
+/*
+       Called when the child process has exited.
+*/
 static int pakfire_jail_exited(sd_event_source* source, const siginfo_t* si, void* data) {
        struct pakfire_jail_exec* ctx = data;
        struct pakfire_jail* jail = ctx->jail;
@@ -2320,6 +2278,16 @@ PAKFIRE_EXPORT int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv
                goto ERROR;
 #endif /* ENABLE_DEBUG */
 
+       // Setup the timer
+       if (jail->timeout) {
+               r = sd_event_add_time_relative(ctx.loop, &ctx.timeout, CLOCK_MONOTONIC,
+                               jail->timeout * 1000000, 0, pakfire_jail_timer, &ctx);
+               if (r < 0) {
+                       CTX_ERROR(jail->ctx, "Could not setup timer: %s\n", strerror(-r));
+                       goto ERROR;
+               }
+       }
+
        // Configure child process
        struct clone_args args = {
                .flags =