4244896: (process) Provide System.getPid(), System.killProcess(String pid)

Reviewed-by: alanb
This commit is contained in:
Rob McKenna 2012-06-26 13:27:26 +01:00
parent d558c37a5b
commit 54ddaf5ab7
9 changed files with 598 additions and 26 deletions

View file

@ -26,7 +26,7 @@
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
* 4947220 7018606 7034570
* 4947220 7018606 7034570 4244896
* @summary Basic tests for Process and Environment Variable code
* @run main/othervm/timeout=300 Basic
* @author Martin Buchholz
@ -38,6 +38,7 @@ import static java.lang.ProcessBuilder.Redirect.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.security.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@ -636,6 +637,44 @@ public class Basic {
static boolean is() { return is; }
}
static class DelegatingProcess extends Process {
final Process p;
DelegatingProcess(Process p) {
this.p = p;
}
@Override
public void destroy() {
p.destroy();
}
@Override
public int exitValue() {
return p.exitValue();
}
@Override
public int waitFor() throws InterruptedException {
return p.waitFor();
}
@Override
public OutputStream getOutputStream() {
return p.getOutputStream();
}
@Override
public InputStream getInputStream() {
return p.getInputStream();
}
@Override
public InputStream getErrorStream() {
return p.getErrorStream();
}
}
private static boolean matches(String str, String regex) {
return Pattern.compile(regex).matcher(str).find();
}
@ -2090,6 +2129,112 @@ public class Basic {
policy.setPermissions(new RuntimePermission("setSecurityManager"));
System.setSecurityManager(null);
//----------------------------------------------------------------
// Check that Process.isAlive() &
// Process.waitFor(0, TimeUnit.MILLISECONDS) work as expected.
//----------------------------------------------------------------
try {
List<String> childArgs = new ArrayList<String>(javaChildArgs);
childArgs.add("sleep");
final Process p = new ProcessBuilder(childArgs).start();
long start = System.nanoTime();
if (!p.isAlive() || p.waitFor(0, TimeUnit.MILLISECONDS)) {
fail("Test failed: Process exited prematurely");
}
long end = System.nanoTime();
// give waitFor(timeout) a wide berth (100ms)
if ((end - start) > 100000000)
fail("Test failed: waitFor took too long");
p.destroy();
p.waitFor();
if (p.isAlive() ||
!p.waitFor(0, TimeUnit.MILLISECONDS))
{
fail("Test failed: Process still alive - please terminate " +
p.toString() + " manually");
}
} catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
// Check that Process.waitFor(timeout, TimeUnit.MILLISECONDS)
// works as expected.
//----------------------------------------------------------------
try {
List<String> childArgs = new ArrayList<String>(javaChildArgs);
childArgs.add("sleep");
final Process p = new ProcessBuilder(childArgs).start();
long start = System.nanoTime();
p.waitFor(1000, TimeUnit.MILLISECONDS);
long end = System.nanoTime();
if ((end - start) < 500000000)
fail("Test failed: waitFor didn't take long enough");
p.destroy();
start = System.nanoTime();
p.waitFor(1000, TimeUnit.MILLISECONDS);
end = System.nanoTime();
if ((end - start) > 100000000)
fail("Test failed: waitFor took too long on a dead process.");
} catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
// Check that Process.waitFor(timeout, TimeUnit.MILLISECONDS)
// interrupt works as expected.
//----------------------------------------------------------------
try {
List<String> childArgs = new ArrayList<String>(javaChildArgs);
childArgs.add("sleep");
final Process p = new ProcessBuilder(childArgs).start();
final long start = System.nanoTime();
final Thread thread = new Thread() {
public void run() {
try {
try {
p.waitFor(10000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
return;
}
fail("waitFor() wasn't interrupted");
} catch (Throwable t) { unexpected(t); }}};
thread.start();
Thread.sleep(1000);
thread.interrupt();
p.destroy();
} catch (Throwable t) { unexpected(t); }
//----------------------------------------------------------------
// Check the default implementation for
// Process.waitFor(long, TimeUnit)
//----------------------------------------------------------------
try {
List<String> childArgs = new ArrayList<String>(javaChildArgs);
childArgs.add("sleep");
final Process proc = new ProcessBuilder(childArgs).start();
DelegatingProcess p = new DelegatingProcess(proc);
long start = System.nanoTime();
p.waitFor(1000, TimeUnit.MILLISECONDS);
long end = System.nanoTime();
if ((end - start) < 500000000)
fail("Test failed: waitFor didn't take long enough");
p.destroy();
start = System.nanoTime();
p.waitFor(1000, TimeUnit.MILLISECONDS);
end = System.nanoTime();
// allow for the less accurate default implementation
if ((end - start) > 200000000)
fail("Test failed: waitFor took too long on a dead process.");
} catch (Throwable t) { unexpected(t); }
}
static void closeStreams(Process p) {

View file

@ -0,0 +1,172 @@
/*
* 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 Test for the various platform specific implementations of
* destroyForcibly.
*/
import java.io.*;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
abstract class ProcessTest implements Runnable {
ProcessBuilder bldr;
Process p;
public Process killProc(boolean force) throws Exception {
if (force) {
p.destroyForcibly();
} else {
p.destroy();
}
return p;
}
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().matches("[Ss]tream [Cc]losed")) {
throw new RuntimeException(e);
}
}
}
public abstract void runTest() throws Exception;
}
class UnixTest extends ProcessTest {
public UnixTest(File script) throws IOException {
script.deleteOnExit();
createScript(script);
bldr = new ProcessBuilder(script.getCanonicalPath());
bldr.redirectErrorStream(true);
bldr.directory(new File("."));
p = bldr.start();
}
void createScript(File processTrapScript) throws IOException {
processTrapScript.deleteOnExit();
FileWriter fstream = new FileWriter(processTrapScript);
try (BufferedWriter out = new BufferedWriter(fstream)) {
out.write("#!/bin/bash\n" +
"echo \\\"ProcessTrap.sh started: trapping SIGTERM/SIGINT\\\"\n" +
"trap bashtrap SIGTERM SIGINT\n" +
"bashtrap()\n" +
"{\n" +
" echo \\\"SIGTERM/SIGINT detected!\\\"\n" +
"}\n" +
"\n" +
"while :\n" +
"do\n" +
" sleep 1;\n" +
"done\n");
}
processTrapScript.setExecutable(true, true);
}
@Override
public void runTest() throws Exception {
killProc(false);
Thread.sleep(1000);
if (!p.isAlive())
throw new RuntimeException("Process terminated prematurely.");
killProc(true).waitFor();
if (p.isAlive())
throw new RuntimeException("Problem terminating the process.");
}
}
class MacTest extends UnixTest {
public MacTest(File script) throws IOException {
super(script);
}
@Override
public void runTest() throws Exception {
// 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 the trap test and go straight to destroyForcibly().
killProc(true).waitFor();
if (p.isAlive())
throw new RuntimeException("Problem terminating the process.");
}
}
class WindowsTest extends ProcessTest {
public WindowsTest() throws IOException {
bldr = new ProcessBuilder("ftp");
bldr.redirectErrorStream(true);
bldr.directory(new File("."));
p = bldr.start();
}
@Override
public void runTest() throws Exception {
killProc(true).waitFor();
}
}
public class DestroyTest {
public static ProcessTest getTest() throws Exception {
String osName = System.getProperty("os.name");
if (osName.startsWith("Windows")) {
return new WindowsTest();
} else if (osName.startsWith("Linux") == true) {
return new UnixTest(
File.createTempFile("ProcessTrap-", ".sh",null));
} else if (osName.startsWith("Mac OS")) {
return new MacTest(
File.createTempFile("ProcessTrap-", ".sh",null));
} else if (osName.equals("SunOS")) {
return new UnixTest(
File.createTempFile("ProcessTrap-", ".sh",null));
}
return null;
}
public static void main(String args[]) throws Exception {
ProcessTest test = getTest();
if (test == null) {
throw new RuntimeException("Unrecognised OS");
} else {
new Thread(test).start();
Thread.sleep(1000);
test.runTest();
}
}
}