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
This commit is contained in:
Sam Lantinga 2024-10-14 21:45:41 -07:00
parent bb764e3106
commit afee27a530
3 changed files with 31 additions and 0 deletions

View file

@ -73,6 +73,14 @@ static bool SetupRedirect(SDL_PropertiesID props, const char *property, HANDLE *
WIN_SetError("DuplicateHandle()"); WIN_SetError("DuplicateHandle()");
return false; 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; return true;
} }

View file

@ -13,6 +13,7 @@ int main(int argc, char *argv[]) {
bool stdin_to_stdout = false; bool stdin_to_stdout = false;
bool read_stdin = false; bool read_stdin = false;
bool stdin_to_stderr = false; bool stdin_to_stderr = false;
SDL_IOStream *log_stdin = NULL;
int exit_code = 0; int exit_code = 0;
state = SDLTest_CommonCreateState(argv, 0); state = SDLTest_CommonCreateState(argv, 0);
@ -45,6 +46,15 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "%s", argv[i + 1]); fprintf(stderr, "%s", argv[i + 1]);
consumed = 2; 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) { } else if (SDL_strcmp(argv[i], "--exit-code") == 0) {
if (i + 1 < argc) { if (i + 1 < argc) {
char *endptr = NULL; char *endptr = NULL;
@ -75,6 +85,7 @@ int main(int argc, char *argv[]) {
"[--print-arguments]", "[--print-arguments]",
"[--print-environment]", "[--print-environment]",
"[--stdin]", "[--stdin]",
"[--log-stdin FILE]",
"[--stdin-to-stdout]", "[--stdin-to-stdout]",
"[--stdout TEXT]", "[--stdout TEXT]",
"[--stdin-to-stderr]", "[--stdin-to-stderr]",
@ -135,6 +146,10 @@ int main(int argc, char *argv[]) {
} }
break; break;
} }
if (log_stdin) {
SDL_WriteIO(log_stdin, buffer, result);
SDL_FlushIO(log_stdin);
}
if (stdin_to_stdout) { if (stdin_to_stdout) {
fwrite(buffer, 1, result, stdout); fwrite(buffer, 1, result, stdout);
fflush(stdout); fflush(stdout);
@ -145,6 +160,10 @@ int main(int argc, char *argv[]) {
} }
} }
if (log_stdin) {
SDL_CloseIO(log_stdin);
}
SDLTest_CommonDestroyState(state); SDLTest_CommonDestroyState(state);
return exit_code; return exit_code;

View file

@ -667,6 +667,8 @@ static int process_testMultiprocessStdinToStdout(void *arg)
const char *process_args[] = { const char *process_args[] = {
data->childprocess_path, data->childprocess_path,
"--stdin-to-stdout", "--stdin-to-stdout",
"--log-stdin",
NULL,
NULL, NULL,
}; };
SDL_Process *process1 = NULL; SDL_Process *process1 = NULL;
@ -680,6 +682,7 @@ static int process_testMultiprocessStdinToStdout(void *arg)
size_t total_read = 0; size_t total_read = 0;
bool finished; bool finished;
process_args[3] = "child1-stdin.txt";
process1 = SDL_CreateProcess(process_args, true); process1 = SDL_CreateProcess(process_args, true);
SDLTest_AssertCheck(process1 != NULL, "SDL_CreateProcess()"); SDLTest_AssertCheck(process1 != NULL, "SDL_CreateProcess()");
if (!process1) { 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_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); SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
SDLTest_AssertPass("About to call SDL_CreateProcessWithProperties"); SDLTest_AssertPass("About to call SDL_CreateProcessWithProperties");
process_args[3] = "child2-stdin.txt";
process2 = SDL_CreateProcessWithProperties(props); process2 = SDL_CreateProcessWithProperties(props);
SDL_DestroyProperties(props); SDL_DestroyProperties(props);
SDLTest_AssertCheck(process2 != NULL, "SDL_CreateProcess()"); SDLTest_AssertCheck(process2 != NULL, "SDL_CreateProcess()");