From ad9103c7672de0b68e99137a266e06292d31806e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 10 Jul 2023 16:14:04 +0800 Subject: [PATCH] Processing (Linux): support timeout --- src/common/processing_linux.c | 58 ++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index 36f263ef3..6681bc681 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -1,10 +1,60 @@ #include "fastfetch.h" #include "common/processing.h" #include "common/io/io.h" +#include "common/time.h" #include #include #include +#include +#include + +#ifdef __linux__ + #include + #include + #include +#endif + +#define FF_WAIT_TIMEOUT 1000 + +int waitpid_timeout(pid_t pid, int* status) +{ + if (FF_WAIT_TIMEOUT <= 0) + return waitpid(pid, status, 0); + + #ifdef __linux__ + + FF_AUTO_CLOSE_FD int pidfd = (int) syscall(SYS_pidfd_open, pid, 0); + if (pidfd >= 0) + { + int res = poll(&(struct pollfd) { .events = POLLIN, .fd = pidfd }, 1, FF_WAIT_TIMEOUT); + if (res > 0) + return (int) waitpid(pid, status, WNOHANG); + else if (res == 0) + { + kill(pid, SIGTERM); + return -ETIME; + } + return -1; + } + + #endif + + uint64_t start = ffTimeGetTick(); + while (true) + { + int res = (int) waitpid(pid, status, WNOHANG); + if (res != 0) + return res; + if (ffTimeGetTick() - start < FF_WAIT_TIMEOUT) + ffTimeSleep(FF_WAIT_TIMEOUT / 10); + else + { + kill(pid, SIGTERM); + return -ETIME; + } + } +} const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) { @@ -33,8 +83,8 @@ const char* ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]) int FF_AUTO_CLOSE_FD childPipeFd = pipes[0]; int status = -1; - if(waitpid(childPid, &status, 0) < 0) - return "waitpid(childPid, &status, 0) failed"; + if(waitpid_timeout(childPid, &status) < 0) + return "waitpid(childPid, &status) failed"; if (!WIFEXITED(status)) return "WIFEXITED(status) == false"; @@ -75,8 +125,8 @@ const char* ffProcessAppendStdErr(FFstrbuf* buffer, char* const argv[]) int FF_AUTO_CLOSE_FD childPipeFd = pipes[0]; int status = -1; - if(waitpid(childPid, &status, WNOHANG) < 0) - return "waitpid(childPid, &status, 0) failed"; + if(waitpid_timeout(childPid, &status) < 0) + return "waitpid(childPid, &status) failed"; if (!WIFEXITED(status)) return "WIFEXITED(status) == false";