From 46d6542eeb050ae275876dc0ea1b945dd8442a5a Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Thu, 4 Jul 2024 06:58:28 +0200 Subject: [PATCH] SapMachine #1693: Add support for starting child processes in an own process group also for Windows --- .../access/JavaLangProcessAccess.java} | 15 ++-- .../jdk/internal/access/SharedSecrets.java | 16 ++++ .../unix/classes/java/lang/ProcessImpl.java | 21 ++++++ .../unix/native/libjava/ProcessImpl_md.c | 11 +++ .../classes/java/lang/ProcessImpl.java | 50 +++++++++++-- .../windows/native/libjava/ProcessImpl_md.c | 36 ++++++++- .../com/sap/jdk/ext/NativeLibHelper.java | 64 ---------------- .../jdk/ext/process/ProcessGroupHelper.java | 18 +++-- .../classes/com/sap/jdk/ext/util/Console.java | 19 ++++- .../ext/process/ProcessGroupHelperImpl.java | 70 ------------------ .../ext/process/ProcessGroupHelperImpl.java | 49 ------------ .../CreateNewProcessGroupOnSpawnTest.java | 74 +++++++++++++------ 12 files changed, 208 insertions(+), 235 deletions(-) rename src/{jdk.sapext/unix/native/libjdksapext/ProcessGroupHelper.c => java.base/share/classes/jdk/internal/access/JavaLangProcessAccess.java} (71%) delete mode 100644 src/jdk.sapext/share/classes/com/sap/jdk/ext/NativeLibHelper.java delete mode 100644 src/jdk.sapext/unix/classes/com/sap/jdk/ext/process/ProcessGroupHelperImpl.java delete mode 100644 src/jdk.sapext/windows/classes/com/sap/jdk/ext/process/ProcessGroupHelperImpl.java diff --git a/src/jdk.sapext/unix/native/libjdksapext/ProcessGroupHelper.c b/src/java.base/share/classes/jdk/internal/access/JavaLangProcessAccess.java similarity index 71% rename from src/jdk.sapext/unix/native/libjdksapext/ProcessGroupHelper.c rename to src/java.base/share/classes/jdk/internal/access/JavaLangProcessAccess.java index b8bee51b631..42978decc39 100644 --- a/src/jdk.sapext/unix/native/libjdksapext/ProcessGroupHelper.c +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangProcessAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024 SAP SE. All rights reserved. + * Copyright (c) 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,15 +23,10 @@ * questions. */ -#include -#include -#include +package jdk.internal.access; -#include "com_sap_jdk_ext_process_ProcessGroupHelperImpl.h" +import java.io.IOException; -JNIEXPORT jint JNICALL Java_com_sap_jdk_ext_process_ProcessGroupHelperImpl_killProcessGroup0 - (JNIEnv *env, jclass ignore, jlong pid_of_leader, jboolean force) -{ - int rc = kill(-(pid_t)pid_of_leader, force ? SIGKILL : SIGTERM); - return ((rc == -1 && errno != 0) ? errno : rc); +public interface JavaLangProcessAccess { + public void destroyProcessGroup(Process leader, boolean force) throws IOException; } diff --git a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java index f56fbe0bccc..2b085b52d35 100644 --- a/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java +++ b/src/java.base/share/classes/jdk/internal/access/SharedSecrets.java @@ -64,6 +64,7 @@ public class SharedSecrets { private static JavaLangModuleAccess javaLangModuleAccess; // SapMachine 2024-06-12: process group extension private static JavaLangProcessBuilderAccess javaLangProcessBuilderAccess; + private static JavaLangProcessAccess javaLangProcessAccess; private static JavaLangRefAccess javaLangRefAccess; private static JavaLangReflectAccess javaLangReflectAccess; private static JavaIOAccess javaIOAccess; @@ -203,6 +204,21 @@ public static JavaLangProcessBuilderAccess getJavaLangProcessBuilderAccess() { return access; } + // SapMachine 2024-07-01: process group extension + public static void setJavaLangProcessAccess(JavaLangProcessAccess jlpa) { + javaLangProcessAccess = jlpa; + } + + // SapMachine 2024-07-01: process group extension + public static JavaLangProcessAccess getJavaLangProcessAccess() { + var access = javaLangProcessAccess; + if (access == null) { + ensureClassInitialized(Process.class); + access = javaLangProcessAccess; + } + return access; + } + public static void setJavaLangRefAccess(JavaLangRefAccess jlra) { javaLangRefAccess = jlra; } diff --git a/src/java.base/unix/classes/java/lang/ProcessImpl.java b/src/java.base/unix/classes/java/lang/ProcessImpl.java index 7d400817af4..075b22283ea 100644 --- a/src/java.base/unix/classes/java/lang/ProcessImpl.java +++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java @@ -47,6 +47,8 @@ import java.security.PrivilegedExceptionAction; import jdk.internal.access.JavaIOFileDescriptorAccess; import jdk.internal.access.SharedSecrets; +//SapMachine 2024-07-01: process group extension +import jdk.internal.access.JavaLangProcessAccess; import jdk.internal.util.OperatingSystem; import jdk.internal.util.StaticProperty; import sun.security.action.GetPropertyAction; @@ -571,8 +573,27 @@ public String toString() { private static native void init(); + // SapMachine 2024-07-01: process group extension + private static native int terminateProcessGroup(long pid, boolean force); + + private void terminateProcessGroup(boolean force) throws IOException { + int rc = terminateProcessGroup(pid, force); + if (rc != 0) { + throw new IOException("Failed to kill process group (errno = " + rc + ")"); + } + } + static { init(); + // SapMachine 2024-07-01: process group extension + SharedSecrets.setJavaLangProcessAccess( + new JavaLangProcessAccess() { + @Override + public void destroyProcessGroup(Process leader, boolean force) throws IOException { + ((ProcessImpl)leader).terminateProcessGroup(force); + } + } + ); } /** diff --git a/src/java.base/unix/native/libjava/ProcessImpl_md.c b/src/java.base/unix/native/libjava/ProcessImpl_md.c index b46aeea023d..6845e992046 100644 --- a/src/java.base/unix/native/libjava/ProcessImpl_md.c +++ b/src/java.base/unix/native/libjava/ProcessImpl_md.c @@ -43,6 +43,9 @@ #include #include #include +/* SapMachine 2024-06-12: process group extension */ +#include +#include #include @@ -820,3 +823,11 @@ Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env, closeSafely(err[0]); err[0] = -1; goto Finally; } + +/* SapMachine 2024-06-12: process group extension */ +JNIEXPORT jint JNICALL +Java_java_lang_ProcessImpl_terminateProcessGroup(JNIEnv *env, jclass ignore, jlong pid_of_leader, jboolean force) +{ + int rc = kill(-(pid_t)pid_of_leader, force ? SIGKILL : SIGTERM); + return ((rc == -1 && errno != 0) ? errno : rc); +} diff --git a/src/java.base/windows/classes/java/lang/ProcessImpl.java b/src/java.base/windows/classes/java/lang/ProcessImpl.java index a016389be55..58d2df3934f 100644 --- a/src/java.base/windows/classes/java/lang/ProcessImpl.java +++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java @@ -45,6 +45,8 @@ import java.util.regex.Pattern; import jdk.internal.access.JavaIOFileDescriptorAccess; +//SapMachine 2024-07-01: process group extension +import jdk.internal.access.JavaLangProcessAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.ref.CleanerFactory; import jdk.internal.misc.Blocker; @@ -61,6 +63,18 @@ final class ProcessImpl extends Process { private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); + // SapMachine 2024-07-01: process group extension + static { + SharedSecrets.setJavaLangProcessAccess( + new JavaLangProcessAccess() { + @Override + public void destroyProcessGroup(Process leader, boolean force) { + ((ProcessImpl)leader).terminateProcessGroup(force); + } + } + ); + } + // Windows platforms support a forcible kill signal. static final boolean SUPPORTS_NORMAL_TERMINATION = false; @@ -159,7 +173,8 @@ static Process start(String cmdarray[], } Process p = new ProcessImpl(cmdarray, envblock, dir, - stdHandles, forceNullOutputStream, redirectErrorStream); + // SapMachine 2024-07-01: process group extension + stdHandles, forceNullOutputStream, redirectErrorStream, createNewProcessGroupOnSpawn); if (redirects != null) { // Copy the handles's if they are to be redirected to another process if (stdHandles[0] >= 0 @@ -426,13 +441,18 @@ private static int countLeadingBackslash(int verificationType, private InputStream stdout_stream; private InputStream stderr_stream; + // SapMachine 2024-07-01: process group extension + private final long hJob; + @SuppressWarnings("removal") private ProcessImpl(String cmd[], final String envblock, final String path, final long[] stdHandles, boolean forceNullOutputStream, - final boolean redirectErrorStream) + final boolean redirectErrorStream, + // SapMachine 2024-07-01: process group extension + final boolean createNewProcessGroupOnSpawn) throws IOException { String cmdstr; @@ -499,11 +519,18 @@ private ProcessImpl(String cmd[], cmd); } + // SapMachine 2024-07-01: process group extension + final long[] local_hJob = (createNewProcessGroupOnSpawn) ? new long[1] : null; handle = create(cmdstr, envblock, path, - stdHandles, redirectErrorStream); + stdHandles, redirectErrorStream, local_hJob); + hJob = (createNewProcessGroupOnSpawn) ? local_hJob[0] : 0; + // Register a cleaning function to close the handle final long local_handle = handle; // local to prevent capture of this - CleanerFactory.cleaner().register(this, () -> closeHandle(local_handle)); + // SapMachine 2024-07-01: process group extension + CleanerFactory.cleaner().register(this, createNewProcessGroupOnSpawn ? + () -> closeHandle(local_handle) : + () -> {closeHandle(local_handle); closeHandle(local_hJob[0]);}); processHandle = ProcessHandleImpl.getInternal(getProcessId0(handle)); @@ -655,6 +682,17 @@ public Process destroyForcibly() { private static native void terminateProcess(long handle); + // SapMachine 2024-07-01: process group extension + private static native void terminateProcessGroup(long hJob); + + private void terminateProcessGroup(boolean force) { + if (hJob == 0) { + destroy(); + } else { + terminateProcessGroup(hJob); + } + } + @Override public long pid() { return processHandle.pid(); @@ -708,7 +746,9 @@ private static synchronized native long create(String cmdstr, String envblock, String dir, long[] stdHandles, - boolean redirectErrorStream) + boolean redirectErrorStream, + // SapMachine 2024-07-01: process group extension + long[] processGroup) throws IOException; /** diff --git a/src/java.base/windows/native/libjava/ProcessImpl_md.c b/src/java.base/windows/native/libjava/ProcessImpl_md.c index 127c27981ba..84436d9f161 100644 --- a/src/java.base/windows/native/libjava/ProcessImpl_md.c +++ b/src/java.base/windows/native/libjava/ProcessImpl_md.c @@ -270,7 +270,9 @@ static jlong processCreate( const jchar *penvBlock, const jchar *pdir, jlong *handles, - jboolean redirectErrorStream) + jboolean redirectErrorStream, + /* SapMachine 2024-07-01: process group extension */ + jlongArray processGroup) { jlong ret = 0L; STARTUPINFOW si = {sizeof(si)}; @@ -328,6 +330,10 @@ static jlong processCreate( processFlag &= ~CREATE_NO_WINDOW; } + /* SapMachine 2024-07-01: process group extension */ + if (processGroup) + processFlag |= CREATE_SUSPENDED; + si.dwFlags = STARTF_USESTDHANDLES; if (!CreateProcessW( NULL, /* executable name */ @@ -343,6 +349,17 @@ static jlong processCreate( { win32Error(env, L"CreateProcess"); } else { + /* SapMachine 2024-07-01: process group extension */ + if (processGroup) { + __declspec(align(8)) HANDLE hJob = CreateJobObject(NULL, NULL); + if (!hJob) { + win32Error(env, L"CreateJobObject"); + } else { + (*env)->SetLongArrayRegion(env, processGroup, 0, 1, (jlong *) &hJob); + AssignProcessToJobObject(hJob, pi.hProcess); + } + ResumeThread(pi.hThread); + } closeSafely(pi.hThread); ret = (jlong)pi.hProcess; } @@ -364,7 +381,9 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, jstring envBlock, jstring dir, jlongArray stdHandles, - jboolean redirectErrorStream) + jboolean redirectErrorStream, + /* SapMachine 2024-07-01: process group extension */ + jlongArray processGroup) { jlong ret = 0; if (cmd != NULL && stdHandles != NULL) { @@ -393,7 +412,9 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, penvBlock, pdir, handles, - redirectErrorStream); + redirectErrorStream, + /* SapMachine 2024-07-01: process group extension */ + processGroup); free(pcmdCopy); // free mutable command line } (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0); @@ -477,6 +498,15 @@ Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle return (jboolean) CloseHandle((HANDLE) handle); } +/* SapMachine 2024-07-01: process group extension */ +JNIEXPORT void JNICALL +Java_java_lang_ProcessImpl_terminateProcessGroup(JNIEnv *env, jclass ignored, jlong hJob) +{ + if (TerminateJobObject((HANDLE) hJob, 1) == 0) { + win32Error(env, L"TerminateJobObject"); + } +} + JNIEXPORT jlong JNICALL Java_java_lang_ProcessImpl_openForAtomicAppend(JNIEnv *env, jclass ignored, jstring path) { diff --git a/src/jdk.sapext/share/classes/com/sap/jdk/ext/NativeLibHelper.java b/src/jdk.sapext/share/classes/com/sap/jdk/ext/NativeLibHelper.java deleted file mode 100644 index 0621d26ac51..00000000000 --- a/src/jdk.sapext/share/classes/com/sap/jdk/ext/NativeLibHelper.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2024 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sap.jdk.ext; - -import java.security.AccessController; -import java.security.PrivilegedAction; - -@SuppressWarnings("removal") -public final class NativeLibHelper { - - /** - * The base name of the jdk extensions library. - */ - private static final String LIB_BASE_NAME = "jdksapext"; - - private static volatile boolean loaded; - - private static synchronized void loadLibrary() { - if (loaded) { - return; - } - - if (System.getSecurityManager() == null) { - System.loadLibrary(LIB_BASE_NAME); - } else { - AccessController.doPrivileged((PrivilegedAction) () -> { - System.loadLibrary(LIB_BASE_NAME); - return null; - }); - } - } - - public static void load() { - if (loaded == false) { - loadLibrary(); - } - } - - private NativeLibHelper() { - // don't instantiate - } -} diff --git a/src/jdk.sapext/share/classes/com/sap/jdk/ext/process/ProcessGroupHelper.java b/src/jdk.sapext/share/classes/com/sap/jdk/ext/process/ProcessGroupHelper.java index fe1f773a51e..be7f3003f4f 100644 --- a/src/jdk.sapext/share/classes/com/sap/jdk/ext/process/ProcessGroupHelper.java +++ b/src/jdk.sapext/share/classes/com/sap/jdk/ext/process/ProcessGroupHelper.java @@ -26,20 +26,26 @@ import java.io.IOException; +import jdk.internal.access.JavaLangProcessAccess; +import jdk.internal.access.JavaLangProcessBuilderAccess; +import jdk.internal.access.SharedSecrets; + /** * ProcessGroupHelper provides the possibility to create and terminate process groups. */ public final class ProcessGroupHelper { + private static JavaLangProcessAccess jlpa = SharedSecrets.getJavaLangProcessAccess(); + private static JavaLangProcessBuilderAccess jlpba = SharedSecrets.getJavaLangProcessBuilderAccess(); + /** - * With this API a ProcessBuilder instance can be configured to create a new (Unix) process group upon spawning the process. - * For Windows, a call to this method is void. + * With this API a ProcessBuilder instance can be configured to create a new process group upon spawning the process. * * @param pb The ProcessBuilder that shall be configured. * @param value true if a new process group shall be created, false otherwise. */ public static final void createNewProcessGroupOnSpawn(ProcessBuilder pb, boolean value) { - ProcessGroupHelperImpl.createNewProcessGroupOnSpawn(pb, value); + jlpba.createNewProcessGroupOnSpawn(pb, value); } /** @@ -51,10 +57,8 @@ public static final void createNewProcessGroupOnSpawn(ProcessBuilder pb, boolean * @throws IOException Process not alive or not a process group leader (safemode = true); Operation failed. * @throws UnsupportedOperationException Operation not supported on this platform */ - public static final void terminateProcessGroupForLeader(Process p, boolean force) - throws IOException, UnsupportedOperationException - { - ProcessGroupHelperImpl.terminateProcessGroupForLeader(p, force); + public static final void terminateProcessGroupForLeader(Process p, boolean force) throws IOException { + jlpa.destroyProcessGroup(p, force); } private ProcessGroupHelper() { diff --git a/src/jdk.sapext/share/classes/com/sap/jdk/ext/util/Console.java b/src/jdk.sapext/share/classes/com/sap/jdk/ext/util/Console.java index 2c174a22eba..ac6ef08fac3 100644 --- a/src/jdk.sapext/share/classes/com/sap/jdk/ext/util/Console.java +++ b/src/jdk.sapext/share/classes/com/sap/jdk/ext/util/Console.java @@ -25,16 +25,29 @@ package com.sap.jdk.ext.util; import java.lang.annotation.Native; - -import com.sap.jdk.ext.NativeLibHelper; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * This class provides methods for console handling. */ +@SuppressWarnings("removal") public final class Console { + /** + * The base name of the jdk extensions library. + */ + private static final String LIB_BASE_NAME = "jdksapext"; + static { - NativeLibHelper.load(); + if (System.getSecurityManager() == null) { + System.loadLibrary(LIB_BASE_NAME); + } else { + AccessController.doPrivileged((PrivilegedAction) () -> { + System.loadLibrary(LIB_BASE_NAME); + return null; + }); + } } /** diff --git a/src/jdk.sapext/unix/classes/com/sap/jdk/ext/process/ProcessGroupHelperImpl.java b/src/jdk.sapext/unix/classes/com/sap/jdk/ext/process/ProcessGroupHelperImpl.java deleted file mode 100644 index e4a91a89206..00000000000 --- a/src/jdk.sapext/unix/classes/com/sap/jdk/ext/process/ProcessGroupHelperImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2018, 2024 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sap.jdk.ext.process; - -import java.io.IOException; - -import com.sap.jdk.ext.NativeLibHelper; -import jdk.internal.access.JavaLangProcessBuilderAccess; -import jdk.internal.access.SharedSecrets; - -/** - * ProcessGroupHelper provides the possibility to create and terminate process groups. - */ -public final class ProcessGroupHelperImpl { - - private static JavaLangProcessBuilderAccess jlpba = SharedSecrets.getJavaLangProcessBuilderAccess(); - - static { - NativeLibHelper.load(); - } - - /** - * Native method that calls kill. - * - * @param pid Process id of the process leading the process group. - * @param force Kill forcibly or politely. - * - * @return 0 in case of success, not 0 otherwise. - */ - private static native int killProcessGroup0(long pid, boolean force); - - static final void createNewProcessGroupOnSpawn(ProcessBuilder pb, boolean value) { - jlpba.createNewProcessGroupOnSpawn(pb, value); - } - - static final void terminateProcessGroupForLeader(Process p, boolean force) - throws IOException - { - int rc = killProcessGroup0(p.toHandle().pid(), force); - if (rc != 0) { - throw new IOException("Failed to kill process group (errno = " + rc + ")"); - } - } - - private ProcessGroupHelperImpl() { - // don't instantiate - } -} diff --git a/src/jdk.sapext/windows/classes/com/sap/jdk/ext/process/ProcessGroupHelperImpl.java b/src/jdk.sapext/windows/classes/com/sap/jdk/ext/process/ProcessGroupHelperImpl.java deleted file mode 100644 index aef266c7a5f..00000000000 --- a/src/jdk.sapext/windows/classes/com/sap/jdk/ext/process/ProcessGroupHelperImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2018, 2024 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sap.jdk.ext.process; - -import java.io.IOException; - -/** - * ProcessGroupHelper provides the possibility to create and terminate process groups. - */ -final class ProcessGroupHelperImpl { - - static final void createNewProcessGroupOnSpawn(ProcessBuilder pb, boolean value) { - // not implemented on Windows - throw new UnsupportedOperationException("Unsupported on Windows."); - } - - static final void terminateProcessGroupForLeader(Process p, boolean force) - throws IOException - { - // not implemented on Windows - throw new UnsupportedOperationException("Unsupported on Windows."); - } - - private ProcessGroupHelperImpl() { - // don't instantiate - } -} diff --git a/test/jdk/java/lang/ProcessBuilder/CreateNewProcessGroupOnSpawnTest.java b/test/jdk/java/lang/ProcessBuilder/CreateNewProcessGroupOnSpawnTest.java index ea9fca20b66..0c5a9603b34 100644 --- a/test/jdk/java/lang/ProcessBuilder/CreateNewProcessGroupOnSpawnTest.java +++ b/test/jdk/java/lang/ProcessBuilder/CreateNewProcessGroupOnSpawnTest.java @@ -23,13 +23,14 @@ import java.util.concurrent.TimeUnit; +import jdk.test.lib.Platform; + import com.sap.jdk.ext.process.ProcessGroupHelper; /** * @test * @summary Tests the SapMachine feature to use process groups via ProcessBuilder. * Test that the process group id of the sub process is different from the parent process group id. - * @requires (os.family != "windows") * @library /test/lib * @run main CreateNewProcessGroupOnSpawnTest */ @@ -40,14 +41,25 @@ public class CreateNewProcessGroupOnSpawnTest { public static void main(String[] args) throws Throwable { - System.loadLibrary("CreateNewProcessGroupOnSpawnTest"); + if (!Platform.isWindows()) { + System.loadLibrary("CreateNewProcessGroupOnSpawnTest"); + } // Retrieve my process group id long mypid = ProcessHandle.current().pid(); - long mypgid = getpgid0(mypid); - System.out.println("My pid: " + mypgid + " my pgid: " + mypgid); - if (mypid <= 0 || mypgid <= 0) { - throw new RuntimeException("Unexpected value for own processid"); + long mypgid = -1; + + if (Platform.isWindows()) { + System.out.println("My pid: " + mypid); + if (mypid <= 0) { + throw new RuntimeException("Unexpected value for own processid"); + } + } else { + mypgid = getpgid0(mypid); + System.out.println("My pid: " + mypid + " my pgid: " + mypgid); + if (mypid <= 0 || mypgid <= 0) { + throw new RuntimeException("Unexpected value for own processid"); + } } ProcessBuilder pb = new ProcessBuilder("sleep", "120"); @@ -57,16 +69,23 @@ public static void main(String[] args) throws Throwable { // Retrieve process group id System.out.println("Child started: " + p.toHandle()); long childpid = p.toHandle().pid(); - long childpgid = getpgid0(childpid); - System.out.println("Child pid: " + childpid + " child pgid: " + childpgid); - if (childpgid <= 0 || childpid <= 0) { - throw new RuntimeException("Unexpected value for child processid"); - } - System.out.println("We expect child to be in our process group."); - if (childpgid == mypgid) { - System.out.println("Ok: Child created in my process group as expected."); + if (Platform.isWindows()) { + System.out.println("Child pid: " + childpid); + if (childpid <= 0) { + throw new RuntimeException("Unexpected value for child processid"); + } } else { - throw new RuntimeException("Error: child not in my process group."); + long childpgid = getpgid0(childpid); + System.out.println("Child pid: " + childpid + " child pgid: " + childpgid); + if (childpid <= 0 || childpgid <= 0) { + throw new RuntimeException("Unexpected value for child processid"); + } + System.out.println("We expect child to be in our process group."); + if (childpgid == mypgid) { + System.out.println("Ok: Child created in my process group as expected."); + } else { + throw new RuntimeException("Error: child not in my process group."); + } } } finally { // clean up @@ -82,16 +101,23 @@ public static void main(String[] args) throws Throwable { // Retrieve process group id System.out.println("Child started: " + p.toHandle()); long childpid = p.toHandle().pid(); - long childpgid = getpgid0(childpid); - System.out.println("Child pid: " + childpid + " child pgid: " + childpgid); - if (childpgid <= 0 || childpid <= 0) { - throw new RuntimeException("Unexpected value for child processid"); - } - System.out.println("We expect child to be pg leader."); - if (childpgid == childpid) { - System.out.println("Ok: Child created in its own process group."); + if (Platform.isWindows()) { + System.out.println("Child pid: " + childpid); + if (childpid <= 0) { + throw new RuntimeException("Unexpected value for child processid"); + } } else { - throw new RuntimeException("Error: child not in its own process group."); + long childpgid = getpgid0(childpid); + System.out.println("Child pid: " + childpid + " child pgid: " + childpgid); + if (childpid <= 0 || childpgid <= 0) { + throw new RuntimeException("Unexpected value for child processid"); + } + System.out.println("We expect child to be pg leader."); + if (childpgid == childpid) { + System.out.println("Ok: Child created in its own process group."); + } else { + throw new RuntimeException("Error: child not in its own process group."); + } } ProcessGroupHelper.terminateProcessGroupForLeader(p, false); p.waitFor(1, TimeUnit.SECONDS);