diff --git a/src/common/io/io.h b/src/common/io/io.h index 2bb6e6e23..4eabaed04 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -222,6 +222,8 @@ static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char* return false; } +FFNativeFD ffGetNullFD(void); + #ifdef _WIN32 // Only O_RDONLY is supported HANDLE openat(HANDLE dfd, const char* fileName, bool directory); diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 8e354cd79..90560f3f6 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -358,3 +358,12 @@ void ffListFilesRecursively(const char* path, bool pretty) ffStrbufEnsureEndsWithC(&folder, '/'); listFilesRecursively(folder.length, &folder, 0, NULL, pretty); } + +FFNativeFD ffGetNullFD(void) +{ + static FFNativeFD hNullFile = -1; + if (hNullFile != -1) + return hNullFile; + hNullFile = open("/dev/null", O_WRONLY | O_CLOEXEC); + return hNullFile; +} diff --git a/src/common/processing_linux.c b/src/common/processing_linux.c index 701ca4833..23e4d0297 100644 --- a/src/common/processing_linux.c +++ b/src/common/processing_linux.c @@ -63,11 +63,21 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use if(ffPipe2(pipes, O_CLOEXEC) == -1) return "pipe() failed"; + pid_t childPid = -1; + int nullFile = ffGetNullFD(); + + #if !(__ANDROID__ || __OpenBSD__) + + // NetBSD / Darwin: native syscall + // Linux (glibc): clone3-execve + // FreeBSD: vfork-execve + // illumos: vforkx-execve + // OpenBSD / Android (bionic): fork-execve + posix_spawn_file_actions_t file_actions; posix_spawn_file_actions_init(&file_actions); posix_spawn_file_actions_adddup2(&file_actions, pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO); - posix_spawn_file_actions_addopen(&file_actions, useStdErr ? STDOUT_FILENO : STDERR_FILENO, "/dev/null", O_WRONLY, 0); - pid_t childPid = -1; + posix_spawn_file_actions_adddup2(&file_actions, nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO); static char* oldLang = NULL; static int langIndex = -1; @@ -113,13 +123,38 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use posix_spawn_file_actions_destroy(&file_actions); - close(pipes[1]); if (ret != 0) { close(pipes[0]); + close(pipes[1]); return "posix_spawnp() failed"; } + #else + + // https://github.com/termux/termux-packages/issues/25369 + childPid = fork(); + if(childPid == -1) + { + close(pipes[0]); + close(pipes[1]); + return "fork() failed"; + } + + if(childPid == 0) + { + //Child + dup2(pipes[1], useStdErr ? STDERR_FILENO : STDOUT_FILENO); + dup2(nullFile, useStdErr ? STDOUT_FILENO : STDERR_FILENO); + putenv("LANG=C.UTF-8"); + execvp(argv[0], argv); + _exit(127); + } + + #endif + + close(pipes[1]); + int FF_AUTO_CLOSE_FD childPipeFd = pipes[0]; char str[FF_PIPE_BUFSIZ];