From afee27a5304b5dec9a8694cb408f877bf1c58d6a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 14 Oct 2024 21:45:41 -0700
Subject: [PATCH] Make sure stdio handles are in blocking mode
Standard I/O doesn't work well with non-blocking handles, so make sure any pipes are in blocking mode before launching child processes.
Fixes https://github.com/libsdl-org/SDL/issues/10998
---
src/process/windows/SDL_windowsprocess.c | 8 ++++++++
test/childprocess.c | 19 +++++++++++++++++++
test/testprocess.c | 4 ++++
3 files changed, 31 insertions(+)
diff --git a/src/process/windows/SDL_windowsprocess.c b/src/process/windows/SDL_windowsprocess.c
index abfacc21b0f50..dc2001439f445 100644
--- a/src/process/windows/SDL_windowsprocess.c
+++ b/src/process/windows/SDL_windowsprocess.c
@@ -73,6 +73,14 @@ static bool SetupRedirect(SDL_PropertiesID props, const char *property, HANDLE *
WIN_SetError("DuplicateHandle()");
return false;
}
+
+ if (GetFileType(*result) == FILE_TYPE_PIPE) {
+ DWORD wait_mode = PIPE_WAIT;
+ if (!SetNamedPipeHandleState(*result, &wait_mode, NULL, NULL)) {
+ WIN_SetError("SetNamedPipeHandleState()");
+ return false;
+ }
+ }
return true;
}
diff --git a/test/childprocess.c b/test/childprocess.c
index dede17717d59c..333fc3c9732e2 100644
--- a/test/childprocess.c
+++ b/test/childprocess.c
@@ -13,6 +13,7 @@ int main(int argc, char *argv[]) {
bool stdin_to_stdout = false;
bool read_stdin = false;
bool stdin_to_stderr = false;
+ SDL_IOStream *log_stdin = NULL;
int exit_code = 0;
state = SDLTest_CommonCreateState(argv, 0);
@@ -45,6 +46,15 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "%s", argv[i + 1]);
consumed = 2;
}
+ } else if (SDL_strcmp(argv[i], "--log-stdin") == 0) {
+ if (i + 1 < argc) {
+ log_stdin = SDL_IOFromFile(argv[i + 1], "w");
+ if (!log_stdin) {
+ fprintf(stderr, "Couldn't open %s\n", argv[i + 1]);
+ return 2;
+ }
+ consumed = 2;
+ }
} else if (SDL_strcmp(argv[i], "--exit-code") == 0) {
if (i + 1 < argc) {
char *endptr = NULL;
@@ -75,6 +85,7 @@ int main(int argc, char *argv[]) {
"[--print-arguments]",
"[--print-environment]",
"[--stdin]",
+ "[--log-stdin FILE]",
"[--stdin-to-stdout]",
"[--stdout TEXT]",
"[--stdin-to-stderr]",
@@ -135,6 +146,10 @@ int main(int argc, char *argv[]) {
}
break;
}
+ if (log_stdin) {
+ SDL_WriteIO(log_stdin, buffer, result);
+ SDL_FlushIO(log_stdin);
+ }
if (stdin_to_stdout) {
fwrite(buffer, 1, result, stdout);
fflush(stdout);
@@ -145,6 +160,10 @@ int main(int argc, char *argv[]) {
}
}
+ if (log_stdin) {
+ SDL_CloseIO(log_stdin);
+ }
+
SDLTest_CommonDestroyState(state);
return exit_code;
diff --git a/test/testprocess.c b/test/testprocess.c
index 5f47010e186e8..425b445151835 100644
--- a/test/testprocess.c
+++ b/test/testprocess.c
@@ -667,6 +667,8 @@ static int process_testMultiprocessStdinToStdout(void *arg)
const char *process_args[] = {
data->childprocess_path,
"--stdin-to-stdout",
+ "--log-stdin",
+ NULL,
NULL,
};
SDL_Process *process1 = NULL;
@@ -680,6 +682,7 @@ static int process_testMultiprocessStdinToStdout(void *arg)
size_t total_read = 0;
bool finished;
+ process_args[3] = "child1-stdin.txt";
process1 = SDL_CreateProcess(process_args, true);
SDLTest_AssertCheck(process1 != NULL, "SDL_CreateProcess()");
if (!process1) {
@@ -692,6 +695,7 @@ static int process_testMultiprocessStdinToStdout(void *arg)
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_POINTER, SDL_GetPointerProperty(SDL_GetProcessProperties(process1), SDL_PROP_PROCESS_STDOUT_POINTER, NULL));
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
SDLTest_AssertPass("About to call SDL_CreateProcessWithProperties");
+ process_args[3] = "child2-stdin.txt";
process2 = SDL_CreateProcessWithProperties(props);
SDL_DestroyProperties(props);
SDLTest_AssertCheck(process2 != NULL, "SDL_CreateProcess()");