This commit is contained in:
Igor Ignatyev 2015-03-10 21:58:55 +00:00
commit 5a48602086
2 changed files with 91 additions and 88 deletions

View File

@ -24,74 +24,29 @@
/* @test
* @bug 4997445
* @summary Test that with server=y, when VM runs to System.exit() no error happens
*
* @build VMConnection RunToExit Exit0
* @library /lib/testlibrary
* @build jdk.testlibrary.* VMConnection RunToExit Exit0
* @run driver RunToExit
*/
import java.io.InputStream;
import java.io.IOException;
import java.io.File;
import java.io.BufferedInputStream;
import java.net.ServerSocket;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.event.*;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.AttachingConnector;
import java.net.ConnectException;
import java.util.Map;
import java.util.List;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import jdk.testlibrary.ProcessTools;
public class RunToExit {
/* Increment this when ERROR: seen */
static int error_seen = 0;
static volatile int error_seen = 0;
static volatile boolean ready = false;
/*
* Helper class to direct process output to a StringBuffer
*/
static class IOHandler implements Runnable {
private String name;
private BufferedInputStream in;
private StringBuffer buffer;
IOHandler(String name, InputStream in) {
this.name = name;
this.in = new BufferedInputStream(in);
this.buffer = new StringBuffer();
}
static void handle(String name, InputStream in) {
IOHandler handler = new IOHandler(name, in);
Thread thr = new Thread(handler);
thr.setDaemon(true);
thr.start();
}
public void run() {
try {
byte b[] = new byte[100];
for (;;) {
int n = in.read(b, 0, 100);
// The first thing that will get read is
// Listening for transport dt_socket at address: xxxxx
// which shows the debuggee is ready to accept connections.
ready = true;
if (n < 0) {
break;
}
buffer.append(new String(b, 0, n));
}
} catch (IOException ioe) { }
String str = buffer.toString();
if ( str.contains("ERROR:") ) {
error_seen++;
}
System.out.println(name + ": " + str);
}
}
/*
* Find a connector by name
@ -111,24 +66,40 @@ public class RunToExit {
/*
* Launch a server debuggee with the given address
*/
private static Process launch(String address, String class_name) throws IOException {
String exe = System.getProperty("java.home")
+ File.separator + "bin" + File.separator + "java";
String cmd = exe + " " + VMConnection.getDebuggeeVMOptions() +
" -agentlib:jdwp=transport=dt_socket" +
",server=y" + ",suspend=y" + ",address=" + address +
" " + class_name;
private static Process launch(String address, String class_name) throws Exception {
String args[] = new String[]{
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address="
+ address,
class_name
};
args = VMConnection.insertDebuggeeVMOptions(args);
System.out.println("Starting: " + cmd);
ProcessBuilder launcher = ProcessTools.createJavaProcessBuilder(args);
Process p = Runtime.getRuntime().exec(cmd);
System.out.println(launcher.command().stream().collect(Collectors.joining(" ", "Starting: ", "")));
IOHandler.handle("Input Stream", p.getInputStream());
IOHandler.handle("Error Stream", p.getErrorStream());
Process p = ProcessTools.startProcess(
class_name,
launcher,
RunToExit::checkForError,
RunToExit::isTransportListening,
0,
TimeUnit.NANOSECONDS
);
return p;
}
private static boolean isTransportListening(String line) {
return line.startsWith("Listening for transport dt_socket");
}
private static void checkForError(String line) {
if (line.contains("ERROR:")) {
error_seen++;
}
}
/*
* - pick a TCP port
* - Launch a server debuggee: server=y,suspend=y,address=${port}
@ -146,15 +117,6 @@ public class RunToExit {
// launch the server debuggee
Process process = launch(address, "Exit0");
// wait for the debugge to be ready
while (!ready) {
try {
Thread.sleep(1000);
} catch(Exception ee) {
throw ee;
}
}
// attach to server debuggee and resume it so it can exit
AttachingConnector conn = (AttachingConnector)findConnector("com.sun.jdi.SocketAttach");
Map conn_args = conn.defaultArguments();
@ -164,7 +126,16 @@ public class RunToExit {
System.out.println("Connection arguments: " + conn_args);
VirtualMachine vm = conn.attach(conn_args);
VirtualMachine vm = null;
while (vm == null) {
try {
vm = conn.attach(conn_args);
} catch (ConnectException e) {
e.printStackTrace(System.out);
System.out.println("--- Debugee not ready. Retrying in 500ms. ---");
Thread.sleep(500);
}
}
// The first event is always a VMStartEvent, and it is always in
// an EventSet by itself. Wait for it.

View File

@ -88,24 +88,12 @@ public final class ProcessTools {
ProcessBuilder processBuilder,
Consumer<String> consumer)
throws IOException {
Process p = null;
try {
p = startProcess(
name,
processBuilder,
line -> {
if (consumer != null) {
consumer.accept(line);
}
return false;
},
-1,
TimeUnit.NANOSECONDS
);
return startProcess(name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS);
} catch (InterruptedException | TimeoutException e) {
// can't ever happen
// will never happen
throw new RuntimeException(e);
}
return p;
}
/**
@ -133,6 +121,38 @@ public final class ProcessTools {
final Predicate<String> linePredicate,
long timeout,
TimeUnit unit)
throws IOException, InterruptedException, TimeoutException {
return startProcess(name, processBuilder, null, linePredicate, timeout, unit);
}
/**
* <p>Starts a process from its builder.</p>
* <span>The default redirects of STDOUT and STDERR are started</span>
* <p>
* It is possible to wait for the process to get to a warmed-up state
* via {@linkplain Predicate} condition on the STDOUT and monitor the
* in-streams via the provided {@linkplain Consumer}
* </p>
* @param name The process name
* @param processBuilder The process builder
* @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to
* @param linePredicate The {@linkplain Predicate} to use on the STDOUT
* Used to determine the moment the target app is
* properly warmed-up.
* It can be null - in that case the warmup is skipped.
* @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
* @param unit The timeout {@linkplain TimeUnit}
* @return Returns the initialized {@linkplain Process}
* @throws IOException
* @throws InterruptedException
* @throws TimeoutException
*/
public static Process startProcess(String name,
ProcessBuilder processBuilder,
final Consumer<String> lineConsumer,
final Predicate<String> linePredicate,
long timeout,
TimeUnit unit)
throws IOException, InterruptedException, TimeoutException {
System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" ")));
Process p = processBuilder.start();
@ -141,6 +161,18 @@ public final class ProcessTools {
stdout.addPump(new LineForwarder(name, System.out));
stderr.addPump(new LineForwarder(name, System.err));
if (lineConsumer != null) {
StreamPumper.LinePump pump = new StreamPumper.LinePump() {
@Override
protected void processLine(String line) {
lineConsumer.accept(line);
}
};
stdout.addPump(pump);
stderr.addPump(pump);
}
CountDownLatch latch = new CountDownLatch(1);
if (linePredicate != null) {
StreamPumper.LinePump pump = new StreamPumper.LinePump() {