From 7ff015ceaee15f0fca49c1eff6694ffb6f8170c1 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 14 Sep 2024 10:16:20 -0700
Subject: [PATCH] Close file descriptors not used by the child process
---
src/process/posix/SDL_posixprocess.c | 40 ++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/src/process/posix/SDL_posixprocess.c b/src/process/posix/SDL_posixprocess.c
index 3aaef3cef27e8..5331e1c01914c 100644
--- a/src/process/posix/SDL_posixprocess.c
+++ b/src/process/posix/SDL_posixprocess.c
@@ -22,6 +22,7 @@
#ifdef SDL_PROCESS_POSIX
+#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
@@ -102,6 +103,41 @@ static bool GetStreamFD(SDL_PropertiesID props, const char *property, int *resul
return true;
}
+static bool AddFileDescriptorCloseActions(posix_spawn_file_actions_t *fa)
+{
+ DIR *dir = opendir("/proc/self/fd");
+ if (dir) {
+ struct dirent *entry;
+ while ((entry = readdir(dir)) != NULL) {
+ int fd = SDL_atoi(entry->d_name);
+ if (fd <= STDERR_FILENO) {
+ continue;
+ }
+
+ int flags = fcntl(fd, F_GETFD);
+ if (flags < 0 || (flags & FD_CLOEXEC)) {
+ continue;
+ }
+ if (posix_spawn_file_actions_addclose(fa, fd) != 0) {
+ closedir(dir);
+ return SDL_SetError("posix_spawn_file_actions_addclose failed: %s", strerror(errno));
+ }
+ }
+ closedir(dir);
+ } else {
+ for (int fd = sysconf(_SC_OPEN_MAX) - 1; fd > STDERR_FILENO; --fd) {
+ int flags = fcntl(fd, F_GETFD);
+ if (flags < 0 || (flags & FD_CLOEXEC)) {
+ continue;
+ }
+ if (posix_spawn_file_actions_addclose(fa, fd) != 0) {
+ return SDL_SetError("posix_spawn_file_actions_addclose failed: %s", strerror(errno));
+ }
+ }
+ }
+ return true;
+}
+
bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID props)
{
char * const *args = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, NULL);
@@ -137,6 +173,10 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
goto posix_spawn_fail_attr;
}
+ if (!AddFileDescriptorCloseActions(&fa)) {
+ goto posix_spawn_fail_all;
+ }
+
// Background processes don't have access to the terminal
if (process->background) {
if (stdin_option == SDL_PROCESS_STDIO_INHERITED) {