--- old/src/share/classes/java/lang/Process.java Thu May 31 14:50:21 2012 +++ new/src/share/classes/java/lang/Process.java Thu May 31 14:50:20 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2012, Oracle and/or its affiliates. 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 @@ -26,6 +26,7 @@ package java.lang; import java.io.*; +import java.util.concurrent.TimeUnit; /** * The {@link ProcessBuilder#start()} and @@ -91,7 +92,7 @@ * @return the output stream connected to the normal input of the * subprocess */ - abstract public OutputStream getOutputStream(); + public abstract OutputStream getOutputStream(); /** * Returns the input stream connected to the normal output of the @@ -117,7 +118,7 @@ * @return the input stream connected to the normal output of the * subprocess */ - abstract public InputStream getInputStream(); + public abstract InputStream getInputStream(); /** * Returns the input stream connected to the error output of the @@ -138,7 +139,7 @@ * @return the input stream connected to the error output of * the subprocess */ - abstract public InputStream getErrorStream(); + public abstract InputStream getErrorStream(); /** * Causes the current thread to wait, if necessary, until the @@ -156,8 +157,56 @@ * thread while it is waiting, then the wait is ended and * an {@link InterruptedException} is thrown. */ - abstract public int waitFor() throws InterruptedException; + public abstract int waitFor() throws InterruptedException; + + /** + * Causes the current thread to wait, if necessary, until the + * subprocess represented by this {@code Process} object has + * terminated, or the specified waiting time elapses. + * + *

If the subprocess has already terminated then this method returns + * immediately with the value {@code true}. If the process has not + * terminated and the timeout value is less than, or equal to, zero, then + * this method returns immediately with the value {@code false}. + * + *

The default implementation of this methods polls the {@code exitValue} + * to check if the process has terminated. Concrete implementations of this + * class are strongly encouraged to override this method with a more + * efficient implementation. + * + * @param timeout the maximum time to wait + * @param unit the time unit of the {@code timeout} argument + * @return {@code true} if the subprocess has exited and {@code false} if + * the waiting time elapsed before the subprocess has exited. + * @throws InterruptedException if the current thread is interrupted + * while waiting. + * @since 1.8 + */ + public boolean waitFor(long timeout, TimeUnit unit) + throws InterruptedException { + long now = System.nanoTime(); + + long end = now + + (timeout <= 0 ? 0 : TimeUnit.NANOSECONDS.convert(timeout, unit)); + + if (end <= 0) // overflow + end = Long.MAX_VALUE; + long rem = end - now; + do { + try { + exitValue(); + return true; + } catch(IllegalThreadStateException ex) { + if(rem > 0) + Thread.sleep( + Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100)); + } + rem = end - System.nanoTime(); + } while(rem > 0); + return false; + } + /** * Returns the exit value for the subprocess. * @@ -167,11 +216,55 @@ * @throws IllegalThreadStateException if the subprocess represented * by this {@code Process} object has not yet terminated */ - abstract public int exitValue(); + public abstract int exitValue(); /** + * Kills the subprocess. Whether the subprocess represented by this + * {@code Process} object is forcibly terminated or not is + * implementation dependent. + */ + public abstract void destroy(); + + /** * Kills the subprocess. The subprocess represented by this * {@code Process} object is forcibly terminated. + * + *

The default implementation of this method invokes {@link #destroy} + * and so may not forcibly terminate the process. Concrete implementations + * of this class are strongly encouraged to override this method with a + * compliant implementation. {@code Process} objects returned by + * {@link ProcessBuilder#start} and {@link Runtime#exec} are of type that + * overrides this method and so invoking this method will forcibly terminate + * the process. + * + *

Note: The subprocess may not terminate immediately. + * i.e. {@code isAlive()} may return true for a brief period + * after {@code destroyForcibly()} is called, however this method + * may be chained to {@code waitFor()} if needed. + * + * @return the {@code Process} object representing the + * subprocess to be forcibly destroyed. + * @since 1.8 */ - abstract public void destroy(); + public Process destroyForcibly() { + destroy(); + return this; + } + + /** + * Tests whether the subprocess represented by this {@code Process} is + * alive. + * + * @return {@code true} if the subprocess represented by this + * {@code Process} object has not yet terminated. + * @since 1.8 + */ + public boolean isAlive() { + try { + exitValue(); + return false; + } catch(IllegalThreadStateException e) { + return true; + } + } } --- old/src/solaris/classes/java/lang/UNIXProcess.java.bsd Thu May 31 14:50:23 2012 +++ new/src/solaris/classes/java/lang/UNIXProcess.java.bsd Thu May 31 14:50:22 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2012, Oracle and/or its affiliates. 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 @@ -38,6 +38,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Executor; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import java.security.AccessController; import static java.security.AccessController.doPrivileged; import java.security.PrivilegedAction; @@ -211,6 +212,25 @@ } return exitcode; } + + @Override + public synchronized boolean waitFor(long timeout, TimeUnit unit) + throws InterruptedException { + if (hasExited) return true; + if (timeout <= 0) return false; + + long now = System.nanoTime(); + long end = now + TimeUnit.NANOSECONDS.convert(timeout, unit); + if (end <= 0) // overflow + end = Long.MAX_VALUE; + + long rem = end - now; + while (!hasExited && (rem > 0)) { + wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1)); + rem = end - System.nanoTime(); + } + return hasExited; + } public synchronized int exitValue() { if (!hasExited) { @@ -219,8 +239,8 @@ return exitcode; } - private static native void destroyProcess(int pid); - public void destroy() { + private static native void destroyProcess(int pid, boolean force); + private void destroy(boolean force) { // There is a risk that pid will be recycled, causing us to // kill the wrong process! So we only terminate processes // that appear to still be running. Even with this check, @@ -229,7 +249,7 @@ // soon, so this is quite safe. synchronized (this) { if (!hasExited) - destroyProcess(pid); + destroyProcess(pid, force); } try { stdin.close(); } catch (IOException ignored) {} try { stdout.close(); } catch (IOException ignored) {} @@ -236,6 +256,21 @@ try { stderr.close(); } catch (IOException ignored) {} } + public void destroy() { + destroy(false); + } + + @Override + public Process destroyForcibly() { + destroy(true); + return this; + } + + @Override + public synchronized boolean isAlive() { + return !hasExited; + } + /* This routine initializes JNI field offsets for the class */ private static native void initIDs(); --- old/src/solaris/classes/java/lang/UNIXProcess.java.linux Thu May 31 14:50:26 2012 +++ new/src/solaris/classes/java/lang/UNIXProcess.java.linux Thu May 31 14:50:25 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2012, Oracle and/or its affiliates. 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 @@ -38,6 +38,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Executor; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; import java.security.AccessController; import static java.security.AccessController.doPrivileged; import java.security.PrivilegedAction; @@ -211,6 +212,25 @@ } return exitcode; } + + @Override + public synchronized boolean waitFor(long timeout, TimeUnit unit) + throws InterruptedException { + if (hasExited) return true; + if (timeout <= 0) return false; + + long now = System.nanoTime(); + long end = now + TimeUnit.NANOSECONDS.convert(timeout, unit); + if (end <= 0) // overflow + end = Long.MAX_VALUE; + + long rem = end - now; + while (!hasExited && (rem > 0)) { + wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1)); + rem = end - System.nanoTime(); + } + return hasExited; + } public synchronized int exitValue() { if (!hasExited) { @@ -219,8 +239,8 @@ return exitcode; } - private static native void destroyProcess(int pid); - public void destroy() { + private static native void destroyProcess(int pid, boolean force); + private void destroy(boolean force) { // There is a risk that pid will be recycled, causing us to // kill the wrong process! So we only terminate processes // that appear to still be running. Even with this check, @@ -229,7 +249,7 @@ // soon, so this is quite safe. synchronized (this) { if (!hasExited) - destroyProcess(pid); + destroyProcess(pid, force); } try { stdin.close(); } catch (IOException ignored) {} try { stdout.close(); } catch (IOException ignored) {} @@ -236,6 +256,21 @@ try { stderr.close(); } catch (IOException ignored) {} } + public void destroy() { + destroy(false); + } + + @Override + public Process destroyForcibly() { + destroy(true); + return this; + } + + @Override + public synchronized boolean isAlive() { + return !hasExited; + } + /* This routine initializes JNI field offsets for the class */ private static native void initIDs(); --- old/src/solaris/classes/java/lang/UNIXProcess.java.solaris Thu May 31 14:50:28 2012 +++ new/src/solaris/classes/java/lang/UNIXProcess.java.solaris Thu May 31 14:50:27 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2012, Oracle and/or its affiliates. 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 @@ -26,6 +26,7 @@ package java.lang; import java.io.*; +import java.util.concurrent.TimeUnit; /* java.lang.Process subclass in the UNIX environment. * @@ -157,6 +158,25 @@ } return exitcode; } + + @Override + public synchronized boolean waitFor(long timeout, TimeUnit unit) + throws InterruptedException { + if (hasExited) return true; + if (timeout <= 0) return false; + + long now = System.nanoTime(); + long end = now + TimeUnit.NANOSECONDS.convert(timeout, unit); + if (end <= 0) // overflow + end = Long.MAX_VALUE; + + long rem = end - now; + while (!hasExited && (rem > 0)) { + wait(Math.max(TimeUnit.NANOSECONDS.toMillis(rem), 1)); + rem = end - System.nanoTime(); + } + return hasExited; + } public synchronized int exitValue() { if (!hasExited) { @@ -165,8 +185,8 @@ return exitcode; } - private static native void destroyProcess(int pid); - public synchronized void destroy() { + private static native void destroyProcess(int pid, boolean force); + private synchronized void destroy(boolean force) { // There is a risk that pid will be recycled, causing us to // kill the wrong process! So we only terminate processes // that appear to still be running. Even with this check, @@ -174,7 +194,7 @@ // is very small, and OSes try hard to not recycle pids too // soon, so this is quite safe. if (!hasExited) - destroyProcess(pid); + destroyProcess(pid, force); try { stdin_stream.close(); if (stdout_inner_stream != null) @@ -187,6 +207,21 @@ } } + public void destroy() { + destroy(false); + } + + @Override + public Process destroyForcibly() { + destroy(true); + return this; + } + + @Override + public synchronized boolean isAlive() { + return !hasExited; + } + // A FileInputStream that supports the deferment of the actual close // operation until the last pending I/O operation on the stream has // finished. This is required on Solaris because we must close the stdin --- old/src/solaris/native/java/lang/UNIXProcess_md.c Thu May 31 14:50:30 2012 +++ new/src/solaris/native/java/lang/UNIXProcess_md.c Thu May 31 14:50:29 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2012, Oracle and/or its affiliates. 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 @@ -955,7 +955,11 @@ } JNIEXPORT void JNICALL -Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, jobject junk, jint pid) +Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, + jobject junk, + jint pid, + jboolean force) { - kill(pid, SIGTERM); + int sig = (force == JNI_TRUE) ? SIGKILL : SIGTERM; + kill(pid, sig); } --- old/src/windows/classes/java/lang/ProcessImpl.java Thu May 31 14:50:33 2012 +++ new/src/windows/classes/java/lang/ProcessImpl.java Thu May 31 14:50:32 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2012, Oracle and/or its affiliates. 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 @@ -37,6 +37,7 @@ import java.lang.ProcessBuilder.Redirect; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.concurrent.TimeUnit; /* This class is for the exclusive use of ProcessBuilder.start() to * create new processes. @@ -255,10 +256,38 @@ return exitValue(); } private static native void waitForInterruptibly(long handle); + @Override + public boolean waitFor(long timeout, TimeUnit unit) + throws InterruptedException { + if (getExitCodeProcess(handle) != STILL_ACTIVE) return true; + if (timeout <= 0) return false; + + long msTimeout = unit.toMillis(timeout); + long ns = unit.toNanos(timeout) % 1000000; + msTimeout += Math.round((double)ns / 1000000); + + waitForTimeoutInterruptibly(handle, msTimeout); + if (Thread.interrupted()) + throw new InterruptedException(); + return (getExitCodeProcess(handle) != STILL_ACTIVE); + } + private static native void waitForTimeoutInterruptibly( + long handle, long timeout); public void destroy() { terminateProcess(handle); } + @Override + public Process destroyForcibly() { + destroy(); + return this; + } private static native void terminateProcess(long handle); + @Override + public boolean isAlive() { + return isProcessAlive(handle); + } + private static native boolean isProcessAlive(long handle); + /** * Create a process using the win32 function CreateProcess. * @@ -297,3 +326,4 @@ private static native boolean closeHandle(long handle); } + --- old/src/windows/native/java/lang/ProcessImpl_md.c Thu May 31 14:50:35 2012 +++ new/src/windows/native/java/lang/ProcessImpl_md.c Thu May 31 14:50:34 2012 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. 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 @@ -296,10 +296,26 @@ HANDLE events[2]; events[0] = (HANDLE) handle; events[1] = JVM_GetThreadInterruptEvent(); + if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, + FALSE, /* Wait for ANY event */ + INFINITE) /* Wait forever */ + == WAIT_FAILED) + win32Error(env, "WaitForMultipleObjects"); +} +JNIEXPORT void JNICALL +Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env, + jclass ignored, + jlong handle, + jlong timeout) +{ + HANDLE events[2]; + DWORD dwTimeout = (DWORD)timeout; + events[0] = (HANDLE) handle; + events[1] = JVM_GetThreadInterruptEvent(); if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, FALSE, /* Wait for ANY event */ - INFINITE) /* Wait forever */ + dwTimeout) /* Wait for dwTimeout */ == WAIT_FAILED) win32Error(env, "WaitForMultipleObjects"); } @@ -310,6 +326,14 @@ TerminateProcess((HANDLE) handle, 1); } +JNIEXPORT jboolean JNICALL +Java_java_lang_ProcessImpl_isProcessAlive(JNIEnv *env, jclass ignored, jlong handle) +{ + DWORD dwExitStatus; + GetExitCodeProcess(handle, &dwExitStatus); + return dwExitStatus == STILL_ACTIVE; +} + JNIEXPORT jboolean JNICALL Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle) { --- /dev/null Thu May 31 14:50:37 2012 +++ new/test/java/lang/Process/ProcessKillTest.java Thu May 31 14:50:36 2012 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. 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. + * + * 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. + */ + +import java.io.*; +import java.util.concurrent.TimeUnit; + +public class ProcessKillTest implements Runnable { + + private Process p; + private static enum OS { + WINDOWS, LINUX, SOLARIS, MAC + } + private static OS currentOS; + + public ProcessKillTest() throws Exception { + String osName = System.getProperty("os.name"); + if(osName.toLowerCase().indexOf("win") == 0) + currentOS = OS.WINDOWS; + else if(osName.toLowerCase().indexOf("lin") == 0) + currentOS = OS.LINUX; + else if(osName.contains("OS X")) + currentOS = OS.MAC; + + ProcessBuilder bldr; + if (currentOS == OS.WINDOWS) + bldr = new ProcessBuilder("ping", "-t", "127.0.0.1"); + else + bldr = new ProcessBuilder("./ProcessTrap.sh"); + bldr.redirectErrorStream(true); + bldr.directory(new File(".")); + p = bldr.start(); + } + + public Process getProc() { + return p; + } + + public void killProc(boolean force) throws Exception { + if(force) { + p.destroyForcibly().waitFor(); + // System.out.println(p.exitValue()); + if ((currentOS == OS.SOLARIS && p.exitValue() != 9) || + ((currentOS == OS.LINUX || currentOS == OS.MAC) + && p.exitValue() != 137)) + throw new RuntimeException("Test failed: wrong exit value"); + } else { + p.destroy(); + } + } + + public boolean isAlive() { + return p.isAlive(); + } + + public void run() { + try { + String line; + BufferedReader is = + new BufferedReader(new InputStreamReader(p.getInputStream())); + while ((line = is.readLine()) != null) + System.err.println("ProcessTrap: " + line); + } catch(IOException e) { + if (!e.getMessage().equals("Stream closed")) { + throw new RuntimeException(e); + } + } + } + + public static void runTest(ProcessKillTest test) throws Exception { + TimeUnit nanos = TimeUnit.NANOSECONDS; + + // this tests that the script is trapping the SIGTERM properly + // and that it doesn't cause the process to terminate. + // since windows would kill the process on a destroy(false) + // we don't perform this test. + // On Mac, it appears that when we close the processes streams + // after a destroy() call, the process terminates with a + // SIGPIPE even if it was trapping the SIGTERM, so as with + // windows, we skip this trap test. + if(currentOS == OS.SOLARIS || currentOS == OS.LINUX) + test.killProc(false); + + long start = System.nanoTime(); + if (!test.isAlive() || + test.getProc().waitFor(0, TimeUnit.MILLISECONDS)) { + throw new RuntimeException( + "Test failed: Process exited prematurely"); + } + long end = System.nanoTime(); + if(nanos.toMillis(end - start) > 10) + throw new RuntimeException( + "Test failed: waitFor took too long"); + + start = System.nanoTime(); + test.getProc().waitFor(3000, TimeUnit.MILLISECONDS); + end = System.nanoTime(); + if(nanos.toMillis(end - start) < 3000) + throw new RuntimeException( + "Test failed: waitFor didn't take long enough"); + + if(currentOS == OS.WINDOWS) + test.killProc(false); // make sure killProc(false) works on win + else + test.killProc(true); // test destroyForcibly(true); + test.getProc().waitFor(); + + start = System.nanoTime(); + if (test.isAlive() || + !test.getProc().waitFor(0, TimeUnit.MILLISECONDS)) { + throw new RuntimeException( + "Test failed: Process hasn't been killed, please terminate " + + test.getProc().toString() + " manually"); + } + end = System.nanoTime(); + if(nanos.toMillis(end - start) > 10) + throw new RuntimeException( + "Test failed: waitFor took too long with a timeout of 0"); + + + start = System.nanoTime(); + test.getProc().waitFor(100, TimeUnit.MILLISECONDS); + end = System.nanoTime(); + if(nanos.toMillis(end - start) > 10) + throw new RuntimeException( + "Test failed: waitFor took too long on dead process"); + + System.out.println("Test passed"); + } + + public static void main(String args[]) throws Exception { + ProcessKillTest test = new ProcessKillTest(); + new Thread(test).start(); + Thread.sleep(1000); + runTest(test); + } +} --- /dev/null Thu May 31 14:50:40 2012 +++ new/test/java/lang/Process/ProcessKillTest.sh Thu May 31 14:50:39 2012 @@ -0,0 +1,92 @@ +#!/bin/bash +# +# Copyright (c) 2012, Oracle and/or its affiliates. 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. +# +# 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. +# + +# @test +# @bug 4244896 +# @summary Adding several methods to the Process class. +# isAlive(): check to see if a process has not exited +# destroyForcibly: implementation dependent force process destroy. +# (e.g. send the process a SIGKILL on Linux/Solaris/Mac) +# waitFor(timeout): add a timeout param to waitFor() +# @run shell ProcessKillTest.sh + +if [ "${TESTSRC}" = "" ] +then TESTSRC=. +fi + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + echo "TESTJAVA not set, selecting " ${TESTJAVA} + echo "If this is incorrect, try setting the variable manually." +fi + +BIT_FLAG="" + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS | Linux | Darwin ) + NULL=/dev/null + PS=":" + FS="/" + CHMOD="${FS}bin${FS}chmod" + THIS_DIR=`pwd` + + TESTSH="#!/bin/bash + echo \"ProcessTrap.sh started, trapping SIGTERM/SIGINT\" + trap bashtrap SIGTERM SIGINT + bashtrap() + { + echo \"SIGTERM/SIGINT detected!\" + } + + while : + do + sleep 1; + done" + + echo "$TESTSH" > ${THIS_DIR}${FS}ProcessTrap.sh + ${CHMOD} a+x ${THIS_DIR}${FS}ProcessTrap.sh + ;; + Windows* | CYGWIN* ) + NULL=NUL + PS=";" + FS="\\" + CHMOD="chmod" + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}ProcessKillTest.java + +${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} ProcessKillTest + +STATUS=$? + +exit $STATUS