From 9b9e235371a5eb867297ed0b49dcff94b1d29050 Mon Sep 17 00:00:00 2001 From: Mikhail Lopatkin Date: Wed, 12 Aug 2026 15:43:16 +0200 Subject: [PATCH] Don't drop "inherit" flag from standard stream handles on Windows This was a useful workaround for ancient Java versions that prevented standard streams from unintentionally leaking into unrelated processes started by ProcessBuilder. As of Java 8 (and final updates of 7), the JDK itself handles that, see https://bugs.openjdk.org/browse/JDK-7147084 The native-platform is Java 8+ today, so the workaround is no longer necessary. Moreover, it is known to cause issues when the standard stream handles go stale, in particular when Gradle daemon closes its System.out and System.err without updating the native side. --- native-platform/src/main/cpp/win.cpp | 30 ------------------- .../platform/internal/Platform.java | 2 +- .../internal/WindowsProcessLauncher.java | 30 ------------------- .../internal/jni/WindowsHandleFunctions.java | 9 ------ 4 files changed, 1 insertion(+), 70 deletions(-) delete mode 100644 native-platform/src/main/java/net/rubygrapefruit/platform/internal/WindowsProcessLauncher.java delete mode 100644 native-platform/src/main/java/net/rubygrapefruit/platform/internal/jni/WindowsHandleFunctions.java diff --git a/native-platform/src/main/cpp/win.cpp b/native-platform/src/main/cpp/win.cpp index 960d848fb..47ad98400 100644 --- a/native-platform/src/main/cpp/win.cpp +++ b/native-platform/src/main/cpp/win.cpp @@ -24,7 +24,6 @@ #include "net_rubygrapefruit_platform_internal_jni_PosixProcessFunctions.h" #include "net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions.h" #include "net_rubygrapefruit_platform_internal_jni_WindowsFileFunctions.h" -#include "net_rubygrapefruit_platform_internal_jni_WindowsHandleFunctions.h" #include "net_rubygrapefruit_platform_internal_jni_WindowsRegistryFunctions.h" #define ALL_COLORS (FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN) @@ -940,35 +939,6 @@ Java_net_rubygrapefruit_platform_internal_jni_WindowsConsoleFunctions_clearToEnd } } -void uninheritStream(JNIEnv* env, DWORD stdInputHandle, jobject result) { - HANDLE streamHandle = GetStdHandle(stdInputHandle); - if (streamHandle == NULL) { - // We're not attached to a stdio (eg Desktop application). Ignore. - return; - } - if (streamHandle == INVALID_HANDLE_VALUE) { - mark_failed_with_errno(env, "could not get std handle", result); - return; - } - boolean ok = SetHandleInformation(streamHandle, HANDLE_FLAG_INHERIT, 0); - if (!ok) { - if (GetLastError() != ERROR_INVALID_PARAMETER && GetLastError() != ERROR_INVALID_HANDLE) { - mark_failed_with_errno(env, "could not change std handle", result); - } - } -} - -JNIEXPORT void JNICALL -Java_net_rubygrapefruit_platform_internal_jni_WindowsHandleFunctions_markStandardHandlesUninheritable(JNIEnv* env, jclass target, jobject result) { - uninheritStream(env, STD_INPUT_HANDLE, result); - uninheritStream(env, STD_OUTPUT_HANDLE, result); - uninheritStream(env, STD_ERROR_HANDLE, result); -} - -JNIEXPORT void JNICALL -Java_net_rubygrapefruit_platform_internal_jni_WindowsHandleFunctions_restoreStandardHandles(JNIEnv* env, jclass target, jobject result) { -} - HKEY get_key_from_ordinal(jint keyNum) { return keyNum == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; } diff --git a/native-platform/src/main/java/net/rubygrapefruit/platform/internal/Platform.java b/native-platform/src/main/java/net/rubygrapefruit/platform/internal/Platform.java index df3184023..a6ad37f18 100644 --- a/native-platform/src/main/java/net/rubygrapefruit/platform/internal/Platform.java +++ b/native-platform/src/main/java/net/rubygrapefruit/platform/internal/Platform.java @@ -173,7 +173,7 @@ public T get(Class type, NativeLibraryLoader na return type.cast(new WindowsTerminals()); } if (type.equals(ProcessLauncher.class)) { - return type.cast(new WrapperProcessLauncher(new WindowsProcessLauncher(new DefaultProcessLauncher()))); + return type.cast(new WrapperProcessLauncher(new DefaultProcessLauncher())); } if (type.equals(SystemInfo.class)) { return type.cast(new DefaultSystemInfo()); diff --git a/native-platform/src/main/java/net/rubygrapefruit/platform/internal/WindowsProcessLauncher.java b/native-platform/src/main/java/net/rubygrapefruit/platform/internal/WindowsProcessLauncher.java deleted file mode 100644 index 10c73d2b6..000000000 --- a/native-platform/src/main/java/net/rubygrapefruit/platform/internal/WindowsProcessLauncher.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.rubygrapefruit.platform.internal; - -import net.rubygrapefruit.platform.NativeException; -import net.rubygrapefruit.platform.ProcessLauncher; -import net.rubygrapefruit.platform.internal.jni.WindowsHandleFunctions; - -public class WindowsProcessLauncher implements ProcessLauncher { - private final ProcessLauncher launcher; - - public WindowsProcessLauncher(ProcessLauncher launcher) { - this.launcher = launcher; - } - - public Process start(ProcessBuilder processBuilder) throws NativeException { - FunctionResult result = new FunctionResult(); - WindowsHandleFunctions.markStandardHandlesUninheritable(result); - if (result.isFailed()) { - throw new NativeException(String.format("Could not start '%s': %s", processBuilder.command().get(0), - result.getMessage())); - } - try { - return launcher.start(processBuilder); - } finally { - WindowsHandleFunctions.restoreStandardHandles(result); - if (result.isFailed()) { - throw new NativeException(String.format("Could not restore process handles: %s", result.getMessage())); - } - } - } -} diff --git a/native-platform/src/main/java/net/rubygrapefruit/platform/internal/jni/WindowsHandleFunctions.java b/native-platform/src/main/java/net/rubygrapefruit/platform/internal/jni/WindowsHandleFunctions.java deleted file mode 100644 index 1fbe7d5d5..000000000 --- a/native-platform/src/main/java/net/rubygrapefruit/platform/internal/jni/WindowsHandleFunctions.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.rubygrapefruit.platform.internal.jni; - -import net.rubygrapefruit.platform.internal.FunctionResult; - -public class WindowsHandleFunctions { - public static native void markStandardHandlesUninheritable(FunctionResult result); - - public static native void restoreStandardHandles(FunctionResult result); -}