8333117: Remove support of remote and manual debuggee launchers
Reviewed-by: cjplummer
This commit is contained in:
parent
9ef86da5f8
commit
99e4d77aac
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2024, 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
|
||||
@ -30,55 +30,15 @@ import nsk.share.jdi.ArgumentHandler;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Interface defining methods to control mirror of debuggee (i.e. debugged VM).
|
||||
* Class defining methods to control mirror of debuggee (i.e. debugged VM).
|
||||
*/
|
||||
public interface Debuggee {
|
||||
public class Debuggee extends LocalProcess {
|
||||
|
||||
/** Default prefix for log messages. */
|
||||
public static final String LOG_PREFIX = "debuggee> ";
|
||||
public static final String DEBUGEE_STDOUT_LOG_PREFIX = "debuggee.stdout> ";
|
||||
public static final String DEBUGEE_STDERR_LOG_PREFIX = "debuggee.stderr> ";
|
||||
|
||||
/**
|
||||
* Launch debuggee.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void launch (String[] args) throws IOException;
|
||||
|
||||
/** Return exit status. */
|
||||
public int getStatus ();
|
||||
|
||||
/** Check whether the process has been terminated. */
|
||||
public boolean terminated();
|
||||
|
||||
/** Kill the debuggee VM. */
|
||||
public void killDebuggee ();
|
||||
|
||||
/** Wait until the debuggee VM shutdown or crash. */
|
||||
public int waitForDebuggee () throws InterruptedException;
|
||||
|
||||
/** Get a pipe to write to the debuggee's stdin stream. */
|
||||
public OutputStream getInPipe ();
|
||||
|
||||
/** Get a pipe to read the debuggee's stdout stream. */
|
||||
public InputStream getOutPipe ();
|
||||
|
||||
/** Get a pipe to read the debuggee's stderr stream. */
|
||||
public InputStream getErrPipe ();
|
||||
|
||||
/** Redirect stdout stream to <code>Log</code> */
|
||||
public void redirectStdout(Log log, String prefix);
|
||||
|
||||
/** Redirect stderr stream to <code>Log</code> */
|
||||
public void redirectStderr(Log log, String prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror of locally launched debuggee.
|
||||
*/
|
||||
final class LocalLaunchedDebuggee extends LocalProcess implements Debuggee {
|
||||
|
||||
private IORedirector stdoutRedirector = null;
|
||||
private IORedirector stderrRedirector = null;
|
||||
private IORedirector stdinRedirector = null;
|
||||
@ -90,7 +50,7 @@ final class LocalLaunchedDebuggee extends LocalProcess implements Debuggee {
|
||||
private Launcher launcher = null;
|
||||
|
||||
/** Enwrap the existing <code>VM</code> mirror. */
|
||||
LocalLaunchedDebuggee (Launcher launcher) {
|
||||
Debuggee(Launcher launcher) {
|
||||
super();
|
||||
this.launcher = launcher;
|
||||
}
|
||||
@ -235,70 +195,3 @@ final class LocalLaunchedDebuggee extends LocalProcess implements Debuggee {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mirror of remotely launched debuggee.
|
||||
*/
|
||||
final class RemoteLaunchedDebuggee implements Debuggee {
|
||||
|
||||
/** Launcher that creates this debuggee. */
|
||||
private Launcher launcher = null;
|
||||
|
||||
/** Enwrap the existing <code>VM</code> mirror. */
|
||||
RemoteLaunchedDebuggee (Launcher launcher) {
|
||||
super();
|
||||
this.launcher = launcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch debugee on remote host via <code>Launcher</code> object.
|
||||
*/
|
||||
public void launch(String[] args) throws IOException {
|
||||
String cmdLine = ArgumentHandler.joinArguments(args, "\"");
|
||||
launcher.display("Starting remote java process:\n" + cmdLine);
|
||||
launcher.launchRemoteProcess(args);
|
||||
}
|
||||
|
||||
/** Return exit status of the debuggee VM. */
|
||||
public int getStatus () {
|
||||
return launcher.getRemoteProcessStatus();
|
||||
}
|
||||
|
||||
/** Check whether the debuggee VM has been terminated. */
|
||||
public boolean terminated () {
|
||||
return launcher.isRemoteProcessTerminated();
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Kill the debuggee VM. */
|
||||
public void killDebuggee () {
|
||||
launcher.killRemoteProcess();
|
||||
}
|
||||
|
||||
/** Wait until the debuggee VM shutdown or crash. */
|
||||
public int waitForDebuggee () {
|
||||
return launcher.waitForRemoteProcess();
|
||||
}
|
||||
|
||||
/** Get a pipe to write to the debuggee's stdin stream. */
|
||||
public OutputStream getInPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debuggee's stdout stream. */
|
||||
public InputStream getOutPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debuggee's stderr stream. */
|
||||
public InputStream getErrPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void redirectStdout(Log log, String prefix) {
|
||||
}
|
||||
|
||||
public void redirectStderr(Log log, String prefix) {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2024, 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
|
||||
@ -103,52 +103,21 @@ public class Launcher extends DebugeeBinder {
|
||||
|
||||
String[] jdbCmdArgs = makeJdbCmdLine(classToExecute);
|
||||
|
||||
if (argumentHandler.isLaunchedLocally()) {
|
||||
|
||||
if (argumentHandler.isDefaultConnector()) {
|
||||
|
||||
localDefaultLaunch(jdbCmdArgs, classToExecute);
|
||||
|
||||
} else if (argumentHandler.isRawLaunchingConnector()) {
|
||||
|
||||
localRawLaunch(jdbCmdArgs, classToExecute);
|
||||
|
||||
} else if (argumentHandler.isLaunchingConnector()) {
|
||||
|
||||
localLaunch(jdbCmdArgs, classToExecute);
|
||||
|
||||
} else if (argumentHandler.isAttachingConnector()) {
|
||||
|
||||
localLaunchAndAttach(jdbCmdArgs, classToExecute);
|
||||
|
||||
} else if (argumentHandler.isListeningConnector()) {
|
||||
|
||||
localLaunchAndListen(jdbCmdArgs, classToExecute);
|
||||
|
||||
} else {
|
||||
throw new TestBug("Unexpected connector type for local launch mode"
|
||||
+ argumentHandler.getConnectorType());
|
||||
}
|
||||
|
||||
} else if (argumentHandler.isLaunchedRemotely()) {
|
||||
|
||||
connectToBindServer(classToExecute);
|
||||
|
||||
if (argumentHandler.isAttachingConnector()) {
|
||||
|
||||
remoteLaunchAndAttach(jdbCmdArgs, classToExecute);
|
||||
|
||||
} else if (argumentHandler.isListeningConnector()) {
|
||||
|
||||
remoteLaunchAndListen(jdbCmdArgs, classToExecute);
|
||||
|
||||
} else {
|
||||
throw new TestBug("Unexpected connector type for remote launch mode"
|
||||
+ argumentHandler.getConnectorType());
|
||||
}
|
||||
if (argumentHandler.isDefaultConnector()) {
|
||||
localDefaultLaunch(jdbCmdArgs, classToExecute);
|
||||
} else if (argumentHandler.isRawLaunchingConnector()) {
|
||||
localRawLaunch(jdbCmdArgs, classToExecute);
|
||||
} else if (argumentHandler.isLaunchingConnector()) {
|
||||
localLaunch(jdbCmdArgs, classToExecute);
|
||||
} else if (argumentHandler.isAttachingConnector()) {
|
||||
localLaunchAndAttach(jdbCmdArgs, classToExecute);
|
||||
} else if (argumentHandler.isListeningConnector()) {
|
||||
localLaunchAndListen(jdbCmdArgs, classToExecute);
|
||||
} else {
|
||||
throw new Failure("Unexpected launching mode: " + argumentHandler.getLaunchMode());
|
||||
throw new TestBug("Unexpected connector type for local launch mode"
|
||||
+ argumentHandler.getConnectorType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,11 +167,7 @@ public class Launcher extends DebugeeBinder {
|
||||
if (argumentHandler.isRawLaunchingConnector()) {
|
||||
|
||||
if (argumentHandler.isSocketTransport()) {
|
||||
if (argumentHandler.isLaunchedLocally()) {
|
||||
connectorAddress = argumentHandler.getTransportPort();
|
||||
} else {
|
||||
connectorAddress = argumentHandler.getDebugeeHost() + ":" + argumentHandler.getTransportPort();
|
||||
}
|
||||
connectorAddress = argumentHandler.getTransportPort();
|
||||
} else if (argumentHandler.isShmemTransport() ) {
|
||||
connectorAddress = argumentHandler.getTransportSharedName();
|
||||
} else {
|
||||
@ -247,8 +212,6 @@ public class Launcher extends DebugeeBinder {
|
||||
|
||||
if (argumentHandler.isSocketTransport()) {
|
||||
connect.append("port=" + argumentHandler.getTransportPort().trim());
|
||||
if (argumentHandler.isLaunchedRemotely())
|
||||
connect.append(",hostname=" + argumentHandler.getDebugeeHost().trim());
|
||||
} else if (argumentHandler.isShmemTransport()) {
|
||||
connect.append("name=" + argumentHandler.getTransportSharedName().trim());
|
||||
} else {
|
||||
@ -324,7 +287,7 @@ public class Launcher extends DebugeeBinder {
|
||||
private void localLaunchAndAttach
|
||||
(String[] jdbCmdArgs, String classToExecute) throws IOException {
|
||||
|
||||
debuggee = new LocalLaunchedDebuggee(this);
|
||||
debuggee = new Debuggee(this);
|
||||
String address = makeTransportAddress();
|
||||
String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address);
|
||||
debuggee.launch(javaCmdArgs);
|
||||
@ -346,57 +309,12 @@ public class Launcher extends DebugeeBinder {
|
||||
String address = jdb.waitForListeningJdb();
|
||||
display("Listening address found: " + address);
|
||||
|
||||
debuggee = new LocalLaunchedDebuggee(this);
|
||||
debuggee = new Debuggee(this);
|
||||
String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address);
|
||||
debuggee.launch(javaCmdArgs);
|
||||
|
||||
// jdb.waitForPrompt(0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run test in remote mode using attaching connector.
|
||||
*/
|
||||
private void remoteLaunchAndAttach
|
||||
(String[] jdbCmdArgs, String classToExecute) throws IOException {
|
||||
|
||||
debuggee = new RemoteLaunchedDebuggee(this);
|
||||
String address = makeTransportAddress();
|
||||
String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address);
|
||||
try {
|
||||
debuggee.launch(javaCmdArgs);
|
||||
} catch (IOException e) {
|
||||
throw new Failure("Caught exception while launching debuggee VM process:\n\t"
|
||||
+ e);
|
||||
};
|
||||
|
||||
display("Start jdb attaching to remote debuggee");
|
||||
jdb = Jdb.startAttachingJdb (this, jdbCmdArgs, JDB_STARTED);
|
||||
// jdb.waitForPrompt(0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run test in remote mode using listening connector.
|
||||
*/
|
||||
private void remoteLaunchAndListen
|
||||
(String[] jdbCmdArgs, String classToExecute) throws IOException {
|
||||
|
||||
jdb = new Jdb(this);
|
||||
display("Starting jdb listening to remote debuggee");
|
||||
jdb.launch(jdbCmdArgs);
|
||||
String address = jdb.waitForListeningJdb();
|
||||
display("Listening address found: " + address);
|
||||
|
||||
debuggee = new RemoteLaunchedDebuggee(this);
|
||||
String[] javaCmdArgs = makeCommandLineArgs(classToExecute);
|
||||
try {
|
||||
debuggee.launch(javaCmdArgs);
|
||||
} catch (IOException e) {
|
||||
throw new Failure("Caught exception while launching debuggee VM process:\n\t"
|
||||
+ e);
|
||||
};
|
||||
|
||||
jdb.waitForMessage(0, JDB_STARTED);
|
||||
// jdb.waitForPrompt(0, false);
|
||||
}
|
||||
|
||||
} // End of Launcher
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, 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
|
||||
@ -457,18 +457,6 @@ public class ArgumentHandler extends DebugeeArgumentHandler {
|
||||
}
|
||||
*/
|
||||
|
||||
if (! isLaunchedLocally() && ! isDefaultDebugeeSuspendMode()) {
|
||||
throw new BadOption("inconsistent options: "
|
||||
+ "-debugee.launch=" + getLaunchMode()
|
||||
+ " and -debugee.suspend=" + getDebugeeSuspendMode());
|
||||
}
|
||||
|
||||
if (! isLaunchedLocally() && isLaunchingConnector()) {
|
||||
throw new BadOption("inconsistent options: "
|
||||
+ "-debugee.launch=" + getLaunchMode()
|
||||
+ " and -connector=" + getConnectorType());
|
||||
}
|
||||
|
||||
if (isLaunchingConnector() && ! isDefaultTransport()) {
|
||||
throw new BadOption("inconsistent options: "
|
||||
+ "-connector=" + getConnectorType()
|
||||
|
@ -127,8 +127,7 @@ public class Binder extends DebugeeBinder {
|
||||
* started with launching connector.
|
||||
*/
|
||||
public Debugee makeLocalDebugee(Process process) {
|
||||
LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(process, this);
|
||||
return debugee;
|
||||
return new Debugee(process, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,51 +188,22 @@ public class Binder extends DebugeeBinder {
|
||||
|
||||
prepareForPipeConnection(argumentHandler);
|
||||
|
||||
if (argumentHandler.isLaunchedLocally()) {
|
||||
|
||||
if (argumentHandler.isDefaultConnector()) {
|
||||
debugee = localDefaultLaunchDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isRawLaunchingConnector()) {
|
||||
debugee = localRawLaunchDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isLaunchingConnector()) {
|
||||
debugee = localLaunchDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isAttachingConnector()) {
|
||||
debugee = localLaunchAndAttachDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isListeningConnector()) {
|
||||
debugee = localLaunchAndListenDebugee(vmm, classToExecute, classPath);
|
||||
} else {
|
||||
throw new TestBug("Unexpected connector type for local debugee launch mode"
|
||||
+ argumentHandler.getConnectorType());
|
||||
}
|
||||
|
||||
} else if (argumentHandler.isLaunchedRemotely()) {
|
||||
|
||||
connectToBindServer(classToExecute);
|
||||
|
||||
if (argumentHandler.isAttachingConnector()) {
|
||||
debugee = remoteLaunchAndAttachDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isListeningConnector()) {
|
||||
debugee = remoteLaunchAndListenDebugee(vmm, classToExecute, classPath);
|
||||
} else {
|
||||
throw new TestBug("Unexpected connector type for remote debugee launch mode"
|
||||
+ argumentHandler.getConnectorType());
|
||||
}
|
||||
|
||||
} else if (argumentHandler.isLaunchedManually()) {
|
||||
|
||||
if (argumentHandler.isAttachingConnector()) {
|
||||
debugee = manualLaunchAndAttachDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isListeningConnector()) {
|
||||
debugee = manualLaunchAndListenDebugee(vmm, classToExecute, classPath);
|
||||
} else {
|
||||
throw new TestBug("Unexpected connector type for manual debugee launch mode"
|
||||
+ argumentHandler.getConnectorType());
|
||||
}
|
||||
|
||||
if (argumentHandler.isDefaultConnector()) {
|
||||
debugee = localDefaultLaunchDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isRawLaunchingConnector()) {
|
||||
debugee = localRawLaunchDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isLaunchingConnector()) {
|
||||
debugee = localLaunchDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isAttachingConnector()) {
|
||||
debugee = localLaunchAndAttachDebugee(vmm, classToExecute, classPath);
|
||||
} else if (argumentHandler.isListeningConnector()) {
|
||||
debugee = localLaunchAndListenDebugee(vmm, classToExecute, classPath);
|
||||
} else {
|
||||
throw new Failure("Unexpected debugee launching mode: " + argumentHandler.getLaunchMode());
|
||||
throw new TestBug("Unexpected connector type for local debugee launch mode"
|
||||
+ argumentHandler.getConnectorType());
|
||||
}
|
||||
|
||||
|
||||
return debugee;
|
||||
}
|
||||
|
||||
@ -486,194 +456,6 @@ public class Binder extends DebugeeBinder {
|
||||
|
||||
// -------------------------------------------------- //
|
||||
|
||||
/**
|
||||
* Launch debugee VM remotely via <code>BindServer</code> and connect to it using
|
||||
* <code>AttachingConnector</code>.
|
||||
*/
|
||||
private Debugee remoteLaunchAndAttachDebugee (VirtualMachineManager vmm,
|
||||
String classToExecute,
|
||||
String classPath) {
|
||||
display("Finding connector: " + argumentHandler.getConnectorName() );
|
||||
AttachingConnector connector =
|
||||
(AttachingConnector) findConnector(argumentHandler.getConnectorName(),
|
||||
vmm.attachingConnectors());
|
||||
|
||||
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
|
||||
|
||||
String address = makeTransportAddress();
|
||||
String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
|
||||
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
|
||||
|
||||
display("Starting remote java process:\n\t" + javaCmdLine);
|
||||
Debugee debugee = startRemoteDebugee(cmdLineArgs);
|
||||
|
||||
display("Attaching to debugee");
|
||||
VirtualMachine vm;
|
||||
IOException ioe = null;
|
||||
for (int i = 0; i < CONNECT_TRIES; i++) {
|
||||
try {
|
||||
vm = connector.attach(arguments);
|
||||
display("Debugee attached");
|
||||
debugee.setupVM(vm);
|
||||
return debugee;
|
||||
} catch (IOException e) {
|
||||
display("Attempt #" + i + " to connect to debugee VM failed:\n\t" + e);
|
||||
ioe = e;
|
||||
if (debugee.terminated()) {
|
||||
throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
|
||||
}
|
||||
try {
|
||||
Thread.currentThread().sleep(CONNECT_TRY_DELAY);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
|
||||
+ ie);
|
||||
}
|
||||
} catch (IllegalConnectorArgumentsException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
|
||||
}
|
||||
}
|
||||
throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
|
||||
+ " tries:\n\t" + ioe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch debugee VM remotely via <code>BindServer</code> and connect to it using
|
||||
* <code>ListeningConnector</code>.
|
||||
*/
|
||||
private Debugee remoteLaunchAndListenDebugee (VirtualMachineManager vmm,
|
||||
String classToExecute,
|
||||
String classPath) {
|
||||
display("Finding connector: " + argumentHandler.getConnectorName() );
|
||||
ListeningConnector connector =
|
||||
(ListeningConnector) findConnector(argumentHandler.getConnectorName(),
|
||||
vmm.listeningConnectors());
|
||||
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
|
||||
|
||||
String address = null;
|
||||
try {
|
||||
display("Listening for connection from debugee");
|
||||
address = connector.startListening(arguments);
|
||||
} catch (IllegalConnectorArgumentsException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Caught exception while starting listening debugee VM:\n\t" + e);
|
||||
};
|
||||
|
||||
String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
|
||||
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
|
||||
|
||||
display("Starting remote java process:\n\t" + javaCmdLine);
|
||||
Debugee debugee = startRemoteDebugee(cmdLineArgs);
|
||||
|
||||
display("Waiting for connection from debugee");
|
||||
VirtualMachine vm;
|
||||
IOException ioe = null;
|
||||
for (int i = 0; i < CONNECT_TRIES; i++) {
|
||||
try {
|
||||
vm = connector.accept(arguments);
|
||||
connector.stopListening(arguments);
|
||||
display("Debugee attached");
|
||||
debugee.setupVM(vm);
|
||||
return debugee;
|
||||
} catch (IOException e) {
|
||||
display("Attempt #" + i + " to listen debugee VM failed:\n\t" + e);
|
||||
ioe = e;
|
||||
if (debugee.terminated()) {
|
||||
throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
|
||||
}
|
||||
try {
|
||||
Thread.currentThread().sleep(CONNECT_TRY_DELAY);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
|
||||
+ ie);
|
||||
}
|
||||
} catch (IllegalConnectorArgumentsException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
|
||||
}
|
||||
}
|
||||
throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
|
||||
+ " tries:\n\t" + ioe);
|
||||
}
|
||||
|
||||
// -------------------------------------------------- //
|
||||
|
||||
/**
|
||||
* Prompt to manually launch debugee VM and connect to it using
|
||||
* <code>AttachingConnector</code>.
|
||||
*/
|
||||
private Debugee manualLaunchAndAttachDebugee (VirtualMachineManager vmm,
|
||||
String classToExecute,
|
||||
String classPath) {
|
||||
display("Finding connector: " + argumentHandler.getConnectorName() );
|
||||
AttachingConnector connector =
|
||||
(AttachingConnector) findConnector(argumentHandler.getConnectorName(),
|
||||
vmm.attachingConnectors());
|
||||
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
|
||||
|
||||
String address = makeTransportAddress();
|
||||
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
|
||||
|
||||
display("Starting manual java process:\n\t" + javaCmdLine);
|
||||
ManualLaunchedDebugee debugee = startManualDebugee(javaCmdLine);
|
||||
|
||||
VirtualMachine vm;
|
||||
try {
|
||||
display("Attaching to debugee");
|
||||
vm = connector.attach(arguments);
|
||||
} catch (IllegalConnectorArgumentsException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Caught exception while attaching to debugee VM:\n\t" + e);
|
||||
};
|
||||
display("Debugee attached");
|
||||
|
||||
debugee.setupVM(vm);
|
||||
return debugee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt to manually launch debugee VM and connect to it using
|
||||
* <code>ListeningConnector</code>.
|
||||
*/
|
||||
private Debugee manualLaunchAndListenDebugee (VirtualMachineManager vmm,
|
||||
String classToExecute,
|
||||
String classPath) {
|
||||
display("Finding connector: " + argumentHandler.getConnectorName() );
|
||||
ListeningConnector connector =
|
||||
(ListeningConnector) findConnector(argumentHandler.getConnectorName(),
|
||||
vmm.listeningConnectors());
|
||||
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
|
||||
|
||||
VirtualMachine vm;
|
||||
try {
|
||||
display("Listening for connection from debugee");
|
||||
String address = connector.startListening(arguments);
|
||||
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
|
||||
display("Starting manual java process:\n\t" + javaCmdLine);
|
||||
ManualLaunchedDebugee debugee = startManualDebugee(javaCmdLine);
|
||||
display("Waiting for connection from debugee");
|
||||
vm = connector.accept(arguments);
|
||||
display("Debugee attached");
|
||||
connector.stopListening(arguments);
|
||||
debugee.setupVM(vm);
|
||||
return debugee;
|
||||
} catch (IllegalConnectorArgumentsException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Caught exception while listening to debugee VM:\n\t" + e);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------- //
|
||||
|
||||
/**
|
||||
@ -920,33 +702,6 @@ public class Binder extends DebugeeBinder {
|
||||
return makeLocalDebugee(process);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch remote debuggee process with specified command line arguments
|
||||
* and make initial <code>Debugee</code> mirror.
|
||||
*/
|
||||
protected RemoteLaunchedDebugee startRemoteDebugee(String[] cmdArgs) {
|
||||
try {
|
||||
launchRemoteProcess(cmdArgs);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Caught exception while launching remote debuggee VM process:\n\t"
|
||||
+ e);
|
||||
}
|
||||
|
||||
RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this);
|
||||
return debugee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch manual debuggee process with specified command line arguments
|
||||
* and make initial <code>Debugee</code> mirror.
|
||||
*/
|
||||
protected ManualLaunchedDebugee startManualDebugee(String cmd) {
|
||||
ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this);
|
||||
debugee.launchDebugee(cmd);
|
||||
return debugee;
|
||||
}
|
||||
|
||||
public static String readVMStartExceptionOutput(VMStartException e, PrintStream log) {
|
||||
StringBuffer msg = new StringBuffer();
|
||||
try (InputStream is = e.process().getInputStream()) {
|
||||
@ -995,287 +750,4 @@ public class Binder extends DebugeeBinder {
|
||||
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mirror of locally launched debugee.
|
||||
*/
|
||||
final class LocalLaunchedDebugee extends Debugee {
|
||||
|
||||
/** Enwrap the locally started VM process. */
|
||||
public LocalLaunchedDebugee (Process process, Binder binder) {
|
||||
super(binder);
|
||||
this.process = process;
|
||||
checkTermination = true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Return exit status of the debugee VM. */
|
||||
public int getStatus () {
|
||||
return process.exitValue();
|
||||
}
|
||||
|
||||
/** Check whether the debugee VM has been terminated. */
|
||||
public boolean terminated () {
|
||||
if (process == null)
|
||||
return true;
|
||||
|
||||
try {
|
||||
int value = process.exitValue();
|
||||
return true;
|
||||
} catch (IllegalThreadStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Kill the debugee VM. */
|
||||
protected void killDebugee () {
|
||||
super.killDebugee();
|
||||
if (!terminated()) {
|
||||
log.display("Killing debugee VM process");
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/** Wait until the debugee VM shutdown or crash. */
|
||||
protected int waitForDebugee () throws InterruptedException {
|
||||
int code = process.waitFor();
|
||||
return code;
|
||||
}
|
||||
|
||||
/** Get a pipe to write to the debugee's stdin stream. */
|
||||
protected OutputStream getInPipe () {
|
||||
return process.getOutputStream();
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stdout stream. */
|
||||
protected InputStream getOutPipe () {
|
||||
return process.getInputStream();
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stderr stream. */
|
||||
protected InputStream getErrPipe () {
|
||||
return process.getErrorStream();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mirror of remotely launched debugee.
|
||||
*/
|
||||
final class RemoteLaunchedDebugee extends Debugee {
|
||||
|
||||
/** Enwrap the remotely started VM process. */
|
||||
public RemoteLaunchedDebugee (Binder binder) {
|
||||
super(binder);
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Return exit status of the debugee VM. */
|
||||
public int getStatus () {
|
||||
return binder.getRemoteProcessStatus();
|
||||
}
|
||||
|
||||
/** Check whether the debugee VM has been terminated. */
|
||||
public boolean terminated () {
|
||||
return binder.isRemoteProcessTerminated();
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Kill the debugee VM. */
|
||||
protected void killDebugee () {
|
||||
super.killDebugee();
|
||||
if (!terminated()) {
|
||||
binder.killRemoteProcess();
|
||||
}
|
||||
}
|
||||
|
||||
/** Wait until the debugee VM shutdown or crash. */
|
||||
protected int waitForDebugee () {
|
||||
return binder.waitForRemoteProcess();
|
||||
}
|
||||
|
||||
/** Get a pipe to write to the debugee's stdin stream. */
|
||||
protected OutputStream getInPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stdout stream. */
|
||||
protected InputStream getOutPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stderr stream. */
|
||||
protected InputStream getErrPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void redirectStdout(OutputStream out) {
|
||||
}
|
||||
|
||||
public void redirectStdout(Log log, String prefix) {
|
||||
}
|
||||
|
||||
public void redirectStderr(OutputStream out) {
|
||||
}
|
||||
|
||||
public void redirectStderr(Log log, String prefix) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mirror of manually launched debugee.
|
||||
*/
|
||||
final class ManualLaunchedDebugee extends Debugee {
|
||||
/** Enwrap the manually started VM process. */
|
||||
public ManualLaunchedDebugee (Binder binder) {
|
||||
super(binder);
|
||||
makeInputReader();
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
private int exitCode = 0;
|
||||
private boolean finished = false;
|
||||
private static BufferedReader bin = null;
|
||||
|
||||
public void launchDebugee(String commandLine) {
|
||||
makeInputReader();
|
||||
|
||||
putMessage("Launch target VM using such command line:\n"
|
||||
+ commandLine);
|
||||
String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes");
|
||||
for ( ; ; ) {
|
||||
if (answer.equals("yes"))
|
||||
break;
|
||||
if (answer.equals("no"))
|
||||
throw new Failure ("Unable to manually launch debugee VM");
|
||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
||||
}
|
||||
}
|
||||
|
||||
private static void makeInputReader() {
|
||||
if (bin == null) {
|
||||
bin = new BufferedReader(new InputStreamReader(System.in));
|
||||
}
|
||||
}
|
||||
|
||||
private static void destroyInputReader() {
|
||||
if (bin != null) {
|
||||
try {
|
||||
bin.close();
|
||||
} catch (IOException e) {
|
||||
// e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Caught exception while closing input stream:\n\t" + e);
|
||||
}
|
||||
bin = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void putMessage(String msg) {
|
||||
System.out.println("\n>>> " + msg);
|
||||
}
|
||||
|
||||
private static String askQuestion(String question, String defaultAnswer) {
|
||||
try {
|
||||
System.out.print("\n>>> " + question);
|
||||
System.out.print(" [" + defaultAnswer + "] ");
|
||||
System.out.flush();
|
||||
String answer = bin.readLine();
|
||||
if (answer.equals(""))
|
||||
return defaultAnswer;
|
||||
return answer;
|
||||
} catch (IOException e) {
|
||||
// e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Caught exception while reading answer:\n\t" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return exit status of the debugee VM. */
|
||||
public int getStatus () {
|
||||
if (! finished) {
|
||||
throw new Failure("Unable to get status of debugee VM: process still alive");
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/** Check whether the debugee VM has been terminated. */
|
||||
public boolean terminated () {
|
||||
return finished;
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Kill the debugee VM. */
|
||||
protected void killDebugee () {
|
||||
super.killDebugee();
|
||||
if (!terminated()) {
|
||||
putMessage("Kill launched VM");
|
||||
String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes");
|
||||
for ( ; ; ) {
|
||||
if (answer.equals("yes")) {
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
if (answer.equals("no"))
|
||||
throw new Failure ("Unable to manually kill debugee VM");
|
||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Wait until the debugee VM shutdown or crash. */
|
||||
protected int waitForDebugee () {
|
||||
putMessage("Wait for launched VM to exit.");
|
||||
String answer = askQuestion("What is VM exit code?", "95");
|
||||
for ( ; ; ) {
|
||||
try {
|
||||
exitCode = Integer.parseInt(answer);
|
||||
break;
|
||||
} catch (NumberFormatException e) {
|
||||
answer = askQuestion("Wrong answer. Please type integer value", "95");
|
||||
}
|
||||
}
|
||||
finished = true;
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/** Get a pipe to write to the debugee's stdin stream. */
|
||||
protected OutputStream getInPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stdout stream. */
|
||||
protected InputStream getOutPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stderr stream. */
|
||||
protected InputStream getErrPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void redirectStdout(OutputStream out) {
|
||||
}
|
||||
|
||||
public void redirectStdout(Log log, String prefix) {
|
||||
}
|
||||
|
||||
public void redirectStderr(OutputStream out) {
|
||||
}
|
||||
|
||||
public void redirectStderr(Log log, String prefix) {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
destroyInputReader();
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, 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
|
||||
@ -47,7 +47,7 @@ import java.util.*;
|
||||
* @see Binder
|
||||
* @see DebugeeProcess
|
||||
*/
|
||||
abstract public class Debugee extends DebugeeProcess {
|
||||
public class Debugee extends DebugeeProcess {
|
||||
|
||||
/**
|
||||
* Mirror of the debugee VM. This must be initialized by every
|
||||
@ -68,6 +68,13 @@ abstract public class Debugee extends DebugeeProcess {
|
||||
this.argumentHandler = (ArgumentHandler)binder.getArgumentHandler();
|
||||
}
|
||||
|
||||
protected Debugee (Process process, Binder binder) {
|
||||
super(binder);
|
||||
this.process = process;
|
||||
this.binder = binder;
|
||||
this.argumentHandler = (ArgumentHandler)binder.getArgumentHandler();
|
||||
}
|
||||
|
||||
/** Setup <code>Debugee</code> object with given VM mirror. */
|
||||
public void setupVM(VirtualMachine vm) {
|
||||
if (this.vm != null) {
|
||||
|
@ -98,13 +98,8 @@ final public class Binder extends DebugeeBinder {
|
||||
|
||||
prepareForPipeConnection(argumentHandler);
|
||||
|
||||
if (argumentHandler.isLaunchedRemotely()) {
|
||||
connectToBindServer(classToExecute);
|
||||
debugee = launchDebugee(classToExecute);
|
||||
} else {
|
||||
debugee = launchDebugee(classToExecute);
|
||||
debugee.redirectOutput(log);
|
||||
}
|
||||
debugee = launchDebugee(classToExecute);
|
||||
debugee.redirectOutput(log);
|
||||
|
||||
Transport transport = debugee.connect();
|
||||
|
||||
@ -117,334 +112,16 @@ final public class Binder extends DebugeeBinder {
|
||||
public Debugee launchDebugee (String classToExecute) {
|
||||
|
||||
try {
|
||||
|
||||
if (argumentHandler.isLaunchedLocally()) {
|
||||
LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(this);
|
||||
String address = debugee.prepareTransport(argumentHandler);
|
||||
if (address == null)
|
||||
address = makeTransportAddress();
|
||||
String[] argsArray = makeCommandLineArgs(classToExecute, address);
|
||||
debugee.launch(argsArray);
|
||||
return debugee;
|
||||
}
|
||||
|
||||
if (argumentHandler.isLaunchedRemotely()) {
|
||||
RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this);
|
||||
String address = debugee.prepareTransport(argumentHandler);
|
||||
if (address == null)
|
||||
address = makeTransportAddress();
|
||||
String[] argsArray = makeCommandLineArgs(classToExecute, address);
|
||||
debugee.launch(argsArray);
|
||||
return debugee;
|
||||
}
|
||||
|
||||
if (argumentHandler.isLaunchedManually()) {
|
||||
ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this);
|
||||
String address = debugee.prepareTransport(argumentHandler);
|
||||
if (address == null)
|
||||
address = makeTransportAddress();
|
||||
String cmdLine = makeCommandLineString(classToExecute, address, "\"");
|
||||
debugee.launch(cmdLine);
|
||||
return debugee;
|
||||
}
|
||||
|
||||
throw new TestBug("Unexpected launching mode: "
|
||||
+ argumentHandler.getLaunchMode());
|
||||
Debugee debugee = new Debugee(this);
|
||||
String address = debugee.prepareTransport(argumentHandler);
|
||||
if (address == null)
|
||||
address = makeTransportAddress();
|
||||
String[] argsArray = makeCommandLineArgs(classToExecute, address);
|
||||
debugee.launch(argsArray);
|
||||
return debugee;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Caught exception while launching debugee:\n\t" + e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror of locally launched debugee.
|
||||
*/
|
||||
final class LocalLaunchedDebugee extends Debugee {
|
||||
|
||||
/** Enwrap the existing <code>VM</code> mirror. */
|
||||
public LocalLaunchedDebugee (Binder binder) {
|
||||
super(binder);
|
||||
checkTermination = true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
public void launch(String[] args) throws IOException {
|
||||
String cmdLine = ArgumentHandler.joinArguments(args, "\"");
|
||||
display("Starting java process:\n" + cmdLine);
|
||||
process = binder.launchProcess(args);
|
||||
}
|
||||
|
||||
/** Return exit status of the debugee VM. */
|
||||
public int getStatus () {
|
||||
return process.exitValue();
|
||||
}
|
||||
|
||||
/** Check whether the debugee VM has been terminated. */
|
||||
public boolean terminated () {
|
||||
if (process == null)
|
||||
return true;
|
||||
|
||||
try {
|
||||
int value = process.exitValue();
|
||||
return true;
|
||||
} catch (IllegalThreadStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Kill the debugee VM. */
|
||||
protected void killDebugee () {
|
||||
super.killDebugee();
|
||||
if (!terminated()) {
|
||||
log.display("Killing debugee VM process");
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/** Wait until the debugee VM shutdown or crash. */
|
||||
protected int waitForDebugee () throws InterruptedException {
|
||||
return process.waitFor();
|
||||
}
|
||||
|
||||
/** Get a pipe to write to the debugee's stdin stream. */
|
||||
protected OutputStream getInPipe () {
|
||||
return process.getOutputStream();
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stdout stream. */
|
||||
protected InputStream getOutPipe () {
|
||||
return process.getInputStream();
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stderr stream. */
|
||||
protected InputStream getErrPipe () {
|
||||
return process.getErrorStream();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mirror of remotely launched debugee.
|
||||
*/
|
||||
final class RemoteLaunchedDebugee extends Debugee {
|
||||
|
||||
/** Enwrap the existing <code>VM</code> mirror. */
|
||||
public RemoteLaunchedDebugee (Binder binder) {
|
||||
super(binder);
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
public void launch(String[] args) throws IOException {
|
||||
String cmdLine = ArgumentHandler.joinArguments(args, "\"");
|
||||
display("Starting remote java process:\n" + cmdLine);
|
||||
binder.launchRemoteProcess(args);
|
||||
}
|
||||
|
||||
/** Return exit status of the debugee VM. */
|
||||
public int getStatus () {
|
||||
return binder.getRemoteProcessStatus();
|
||||
}
|
||||
|
||||
/** Check whether the debugee VM has been terminated. */
|
||||
public boolean terminated () {
|
||||
return binder.isRemoteProcessTerminated();
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Kill the debugee VM. */
|
||||
protected void killDebugee () {
|
||||
super.killDebugee();
|
||||
if (!terminated()) {
|
||||
log.display("Killing debugee VM process");
|
||||
binder.killRemoteProcess();
|
||||
}
|
||||
}
|
||||
|
||||
/** Wait until the debugee VM shutdown or crash. */
|
||||
protected int waitForDebugee () {
|
||||
return binder.waitForRemoteProcess();
|
||||
}
|
||||
|
||||
/** Get a pipe to write to the debugee's stdin stream. */
|
||||
protected OutputStream getInPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stdout stream. */
|
||||
protected InputStream getOutPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stderr stream. */
|
||||
protected InputStream getErrPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void redirectStdout(OutputStream out) {
|
||||
}
|
||||
|
||||
public void redirectStdout(Log log, String prefix) {
|
||||
}
|
||||
|
||||
public void redirectStderr(OutputStream out) {
|
||||
}
|
||||
|
||||
public void redirectStderr(Log log, String prefix) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mirror of manually launched debugee.
|
||||
*/
|
||||
final class ManualLaunchedDebugee extends Debugee {
|
||||
|
||||
private int exitCode = 0;
|
||||
private boolean finished = false;
|
||||
private static BufferedReader bin = new BufferedReader(new InputStreamReader(System.in));
|
||||
|
||||
/** Enwrap the existing <code>VM</code> mirror. */
|
||||
public ManualLaunchedDebugee (Binder binder) {
|
||||
super(binder);
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
public void launch(String commandLine) throws IOException {
|
||||
putMessage("Launch target VM using such command line:\n"
|
||||
+ commandLine);
|
||||
String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes");
|
||||
for ( ; ; ) {
|
||||
if (answer.equals("yes"))
|
||||
break;
|
||||
if (answer.equals("no"))
|
||||
throw new Failure ("Unable to manually launch debugee VM");
|
||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
||||
}
|
||||
}
|
||||
|
||||
private void putMessage(String msg) {
|
||||
System.out.println("\n>>> " + msg);
|
||||
}
|
||||
|
||||
private String askQuestion(String question, String defaultAnswer) {
|
||||
try {
|
||||
System.out.print("\n>>> " + question);
|
||||
System.out.print(" [" + defaultAnswer + "] ");
|
||||
System.out.flush();
|
||||
String answer = bin.readLine();
|
||||
if (answer.equals(""))
|
||||
return defaultAnswer;
|
||||
return answer;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Caught exception while reading answer:\n\t" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return exit status of the debugee VM. */
|
||||
public int getStatus () {
|
||||
if (! terminated()) {
|
||||
throw new Failure("Unable to get status of debugee VM: process still alive");
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/** Check whether the debugee VM has been terminated. */
|
||||
public boolean terminated () {
|
||||
if(! finished) {
|
||||
String answer = askQuestion("Has the VM exited?", "no");
|
||||
for ( ; ; ) {
|
||||
if (answer.equals("no"))
|
||||
return false;
|
||||
if (answer.equals("yes")) {
|
||||
finished = true;
|
||||
waitForDebugee();
|
||||
break;
|
||||
}
|
||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
||||
}
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/** Kill the debugee VM. */
|
||||
protected void killDebugee () {
|
||||
super.killDebugee();
|
||||
if (!terminated()) {
|
||||
putMessage("Kill launched VM");
|
||||
String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes");
|
||||
for ( ; ; ) {
|
||||
if (answer.equals("yes")) {
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
if (answer.equals("no"))
|
||||
throw new Failure ("Unable to manually kill debugee VM");
|
||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Wait until the debugee VM shutdown or crash. */
|
||||
protected int waitForDebugee () {
|
||||
putMessage("Wait for launched VM to exit.");
|
||||
String answer = askQuestion("What is VM exit code?", "95");
|
||||
for ( ; ; ) {
|
||||
try {
|
||||
exitCode = Integer.parseInt(answer);
|
||||
break;
|
||||
} catch (NumberFormatException e) {
|
||||
answer = askQuestion("Wrong answer. Please type integer value", "95");
|
||||
}
|
||||
}
|
||||
finished = true;
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/** Get a pipe to write to the debugee's stdin stream. */
|
||||
protected OutputStream getInPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stdout stream. */
|
||||
protected InputStream getOutPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stderr stream. */
|
||||
protected InputStream getErrPipe () {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void redirectStdout(OutputStream out) {
|
||||
}
|
||||
|
||||
public void redirectStdout(Log log, String prefix) {
|
||||
}
|
||||
|
||||
public void redirectStderr(OutputStream out) {
|
||||
}
|
||||
|
||||
public void redirectStderr(Log log, String prefix) {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
bin.close();
|
||||
} catch (IOException e) {
|
||||
log.display("WARNING: Caught IOException while closing InputStream");
|
||||
}
|
||||
bin = null;
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, 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
|
||||
@ -46,7 +46,7 @@ import java.io.*;
|
||||
* @see Transport
|
||||
* @see DebugeeProcess
|
||||
*/
|
||||
abstract public class Debugee extends DebugeeProcess {
|
||||
public class Debugee extends DebugeeProcess {
|
||||
|
||||
/** Binder that creates this debugee. */
|
||||
protected Binder binder = null;
|
||||
@ -63,6 +63,12 @@ abstract public class Debugee extends DebugeeProcess {
|
||||
prefix = "Debugee> ";
|
||||
}
|
||||
|
||||
public void launch(String[] args) throws IOException {
|
||||
String cmdLine = ArgumentHandler.joinArguments(args, "\"");
|
||||
display("Starting java process:\n" + cmdLine);
|
||||
process = binder.launchProcess(args);
|
||||
}
|
||||
|
||||
/** Return <code>Binder</code> of the debugee object. */
|
||||
public Binder getBinder() {
|
||||
return binder;
|
||||
|
@ -57,8 +57,6 @@ import java.net.ServerSocket;
|
||||
* (this works only with <code>-connector=listening</code> and <code>-transport=socket</code>)
|
||||
* <li> <code>-debugee.suspend=[yes|no|default]</code> -
|
||||
* should debugee start in suspend mode or not
|
||||
* <li> <code>-debugee.launch=[local|remote|manual]</code> -
|
||||
* launch and bind to debugee VM locally, remotely (via BindSever) or manually
|
||||
* <li> <code>-debugee.vmhome=</code><<i>path</i>> -
|
||||
* path to JDK used for launching debugee VM
|
||||
* <li> <code>-debugee.vmkind=</code><<i>name</i>> -
|
||||
@ -275,11 +273,8 @@ public class DebugeeArgumentHandler extends ArgumentParser {
|
||||
* @see #isDefaultDebugeeSuspendMode()
|
||||
*/
|
||||
public boolean willDebugeeSuspended() {
|
||||
if (isLaunchedLocally()) {
|
||||
String mode = getDebugeeSuspendMode();
|
||||
return mode.equals("no");
|
||||
}
|
||||
return true;
|
||||
String mode = getDebugeeSuspendMode();
|
||||
return mode.equals("no");
|
||||
}
|
||||
|
||||
private boolean pipePortInited = false;
|
||||
@ -337,54 +332,6 @@ public class DebugeeArgumentHandler extends ArgumentParser {
|
||||
setOption("-", "pipe.port", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return debugee VM launching mode, specified by
|
||||
* <code>-launch.mode</code> command line option, or
|
||||
* "<i>local</i>" string by default.
|
||||
*
|
||||
* Possible values for this option are:
|
||||
* <ul>
|
||||
* <li> "<code>local</code>"
|
||||
* <li> "<code>remote</code>"
|
||||
* <li> "<code>manual</code>"
|
||||
* </ul>
|
||||
*
|
||||
* @see #isLaunchedLocally()
|
||||
* @see #isLaunchedRemotely()
|
||||
* @see #isLaunchedManually()
|
||||
* @see #setRawArguments(String[])
|
||||
*/
|
||||
public String getLaunchMode() {
|
||||
return options.getProperty("debugee.launch", "local");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <i>true</i> if debugee should be launched locally.
|
||||
*
|
||||
* @see #getLaunchMode()
|
||||
*/
|
||||
public boolean isLaunchedLocally() {
|
||||
return getLaunchMode().equals("local");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <i>true</i> if debugee should be launched remotely via
|
||||
* BindServer.
|
||||
*
|
||||
* @see #getLaunchMode()
|
||||
*/
|
||||
public boolean isLaunchedRemotely() {
|
||||
return getLaunchMode().equals("remote");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <i>true</i> if debugee should be launched manually by user.
|
||||
*
|
||||
* @see #getLaunchMode()
|
||||
*/
|
||||
public boolean isLaunchedManually() {
|
||||
return getLaunchMode().equals("manual");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return additional options for launching debugee VM, specified by
|
||||
@ -710,9 +657,7 @@ public class DebugeeArgumentHandler extends ArgumentParser {
|
||||
}
|
||||
|
||||
// option with any nonempty string value
|
||||
if (option.equals("test.host")
|
||||
|| option.equals("debugee.host")
|
||||
|| option.equals("debugee.vmkind")
|
||||
if (option.equals("debugee.vmkind")
|
||||
|| option.equals("debugee.vmhome")
|
||||
|| option.equals("transport.shname")) {
|
||||
if (value.length() <= 0) {
|
||||
@ -748,14 +693,10 @@ public class DebugeeArgumentHandler extends ArgumentParser {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (option.equals("debugee.launch")) {
|
||||
if ((!value.equals("local"))
|
||||
&& (!value.equals("remote"))
|
||||
&& (!value.equals("manual"))) {
|
||||
throw new BadOption(option + ": must be one of: "
|
||||
+ "local, remote, manual " + value);
|
||||
}
|
||||
return true;
|
||||
if (option.equals("debugee.launch")
|
||||
|| option.equals("debugee.host")
|
||||
|| option.equals("test.host")) {
|
||||
throw new RuntimeException("option " + option + " is not supported.");
|
||||
}
|
||||
|
||||
if (option.equals("jvmdi.strict")) {
|
||||
|
@ -35,15 +35,6 @@ import java.util.*;
|
||||
* debuggee VM and to make connection to it using JDI connector or
|
||||
* JDWP transport.
|
||||
* <p>
|
||||
* The present version of <code>Binder</code> allows
|
||||
* to launch debuggee VM either on local machine (<i>local</i> launch mode),
|
||||
* or on remote host using <code>BindServer</code> utility
|
||||
* (<i>remote</i> launch mode). Also there is an ability to launch
|
||||
* debuggee VM manually as a separate process on local or remote machine
|
||||
* (<i>manual</i> launch mode), which is usefull for debugging.
|
||||
* All these launching modes are specified by command line option
|
||||
* <code>-debugee.launch</code> recognized by <code>DebugeeArgumentHandler</code>.
|
||||
* <p>
|
||||
* <code>Binder</code> also makes it possible to establish TCP/IP
|
||||
* connection between debugger and debuggee throw <code>IOPipe</code>
|
||||
* object. This connection allows debugger to communicate with debuggee
|
||||
@ -105,8 +96,6 @@ public class DebugeeBinder extends Log.Logger {
|
||||
}
|
||||
|
||||
// -------------------------------------------------- //
|
||||
|
||||
private BindServerListener bindServerListener = null;
|
||||
private ServerSocket pipeServerSocket = null;
|
||||
|
||||
// -------------------------------------------------- //
|
||||
@ -386,356 +375,12 @@ public class DebugeeBinder extends Log.Logger {
|
||||
return makeCommandLineArgs(classToExecute, makeTransportAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make connection to remote BindServer and start BindServerListener thread.
|
||||
*
|
||||
* @throws IOException if I/O error occured while connecting
|
||||
*/
|
||||
public void connectToBindServer(String taskID) {
|
||||
if (bindServerListener != null) {
|
||||
throw new Failure("Connection to BindServer already exists");
|
||||
}
|
||||
try {
|
||||
bindServerListener = new BindServerListener(this);
|
||||
bindServerListener.setDaemon(true);
|
||||
bindServerListener.connect(taskID);
|
||||
bindServerListener.start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(getOutStream());
|
||||
throw new Failure("Caught exception while connecting to BindServer:\n\t" + e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split string into list of substrings using specified separator.
|
||||
*/
|
||||
private static String[] splitString(String givenString, String separator) {
|
||||
Vector<String> tmpList = new Vector<String>();
|
||||
StringTokenizer tokenizer = new StringTokenizer(givenString, separator);
|
||||
while(tokenizer.hasMoreTokens()) {
|
||||
tmpList.add(tokenizer.nextToken());
|
||||
}
|
||||
String[] list = new String[tmpList.size()];
|
||||
for (int i = 0; i < tmpList.size(); i++) {
|
||||
list[i] = tmpList.elementAt(i);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send command to remote <code>BindServer</code> and receive reply.
|
||||
*
|
||||
* @throws IOException if I/O error occured while launching process
|
||||
*/
|
||||
public synchronized Object sendRemoteCommand(Object command) {
|
||||
try {
|
||||
bindServerListener.sendCommand(command);
|
||||
Object reply = bindServerListener.getReply();
|
||||
return reply;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace(log.getOutStream());
|
||||
throw new Failure("Unexpected exception while sending command to BindServer:\n\t"
|
||||
+ e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch remote process using request to <code>BindServer</code>.
|
||||
*
|
||||
* @throws IOException if I/O error occured
|
||||
*/
|
||||
public void launchRemoteProcess(String[] args) throws IOException {
|
||||
String pathSeparator = System.getProperty("path.separator");
|
||||
BindServer.LaunchDebugee command =
|
||||
new BindServer.LaunchDebugee(args,
|
||||
System.getProperty("file.separator"),
|
||||
System.getProperty("user.dir"),
|
||||
splitString(System.getProperty("java.library.path"), pathSeparator),
|
||||
splitString(System.getProperty("java.class.path"), pathSeparator),
|
||||
splitString(System.getProperty("java.library.path"), pathSeparator));
|
||||
|
||||
Object reply = sendRemoteCommand(command);
|
||||
if (reply instanceof BindServer.OK) {
|
||||
// do nothing
|
||||
} else if (reply instanceof BindServer.RequestFailed) {
|
||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
||||
throw new Failure("BindServer error: " + castedReply.reason);
|
||||
} else {
|
||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return exit status of the remotely launched process
|
||||
* using request to <code>BindServer</code>.
|
||||
*/
|
||||
public int getRemoteProcessStatus () {
|
||||
Object reply = sendRemoteCommand(new BindServer.DebugeeExitCode());
|
||||
if (reply instanceof BindServer.OK) {
|
||||
BindServer.OK castedReply = (BindServer.OK)reply;
|
||||
return (int)castedReply.info;
|
||||
} else if (reply instanceof BindServer.CaughtException) {
|
||||
BindServer.CaughtException castedReply = (BindServer.CaughtException)reply;
|
||||
throw new IllegalThreadStateException(castedReply.reason);
|
||||
} else if (reply instanceof BindServer.RequestFailed) {
|
||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
||||
throw new Failure("BindServer error: " + castedReply.reason);
|
||||
} else {
|
||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the remotely launched process has been terminated
|
||||
* using request to <code>BindServer</code>.
|
||||
*/
|
||||
public boolean isRemoteProcessTerminated () {
|
||||
try {
|
||||
int value = getRemoteProcessStatus();
|
||||
return true;
|
||||
} catch (IllegalThreadStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------- //
|
||||
|
||||
/**
|
||||
* Kill the remotely launched process
|
||||
* using request to <code>BindServer</code>.
|
||||
*/
|
||||
public void killRemoteProcess () {
|
||||
Object reply = sendRemoteCommand(new BindServer.KillDebugee());
|
||||
if (reply instanceof BindServer.OK) {
|
||||
return;
|
||||
} else if (reply instanceof BindServer.RequestFailed) {
|
||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
||||
throw new Failure("BindServer error: " + castedReply.reason);
|
||||
} else {
|
||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the remotely launched process exits or crashes
|
||||
* using request to <code>BindServer</code>.
|
||||
*/
|
||||
public int waitForRemoteProcess () {
|
||||
|
||||
Object reply = sendRemoteCommand(new BindServer.WaitForDebugee(0));
|
||||
if (reply instanceof BindServer.OK) {
|
||||
BindServer.OK castedReply = (BindServer.OK)reply;
|
||||
return (int)castedReply.info;
|
||||
} else if (reply instanceof BindServer.RequestFailed) {
|
||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
||||
throw new Failure("BindServer error: " + castedReply.reason);
|
||||
} else {
|
||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close binder by closing all started threads.
|
||||
*/
|
||||
public void close() {
|
||||
if (bindServerListener != null) {
|
||||
bindServerListener.close();
|
||||
}
|
||||
closePipeServerSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Separate thread for listening connection from <code>BindServer</code>.
|
||||
*/
|
||||
private class BindServerListener extends Thread {
|
||||
private SocketConnection connection = null;
|
||||
private Log.Logger logger = null;
|
||||
|
||||
/** List of received responses from <code>BindServer</code>. */
|
||||
private LinkedList<BindServer.Response> replies = new LinkedList<BindServer.Response>();
|
||||
|
||||
/**
|
||||
* Make thread.
|
||||
*/
|
||||
public BindServerListener(Log.Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish connection to <code>BindServer</code>.
|
||||
*/
|
||||
public void connect(String taskID) throws IOException {
|
||||
String host = argumentHandler.getDebugeeHost();
|
||||
int port = argumentHandler.getBindPortNumber();
|
||||
display("Connecting to BindServer: " + host + ":" + port);
|
||||
connection = new SocketConnection(logger, "BindServer");
|
||||
// connection.setPingTimeout(DebugeeBinder.PING_TIMEOUT);
|
||||
connection.attach(host, port);
|
||||
handshake(taskID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive OK(version) from BindServer and check received version number.
|
||||
*/
|
||||
private void handshake(String taskID) {
|
||||
// receive OK(version)
|
||||
trace(TRACE_LEVEL_ACTIONS, "Waiting for initial OK(version) from BindServer");
|
||||
Object reply = connection.readObject();
|
||||
trace(TRACE_LEVEL_ACTIONS, "Got initial OK(version) from BindServer: " + reply);
|
||||
if (reply instanceof BindServer.RequestFailed) {
|
||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
||||
trace(TRACE_LEVEL_ACTIONS, "Reply is RequestFailed: throw Failure");
|
||||
throw new Failure("BindServer error: " + castedReply.reason);
|
||||
} else if (reply instanceof BindServer.OK) {
|
||||
BindServer.OK castedReply = (BindServer.OK)reply;
|
||||
trace(TRACE_LEVEL_ACTIONS, "Reply is OK: check BindServer version");
|
||||
if (castedReply.info != BindServer.VERSION) {
|
||||
throw new Failure("Wrong version of BindServer: " + castedReply.info
|
||||
+ " (expected: " + BindServer.VERSION + ")");
|
||||
}
|
||||
display("Connected to BindServer: version " + castedReply.info);
|
||||
} else {
|
||||
trace(TRACE_LEVEL_ACTIONS, "Reply is unknown: throw Failure");
|
||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
||||
}
|
||||
|
||||
// send TaskID(id)
|
||||
try {
|
||||
trace(TRACE_LEVEL_ACTIONS, "Sending TaskID(id) to BindServer");
|
||||
sendCommand(new BindServer.TaskID(taskID));
|
||||
trace(TRACE_LEVEL_ACTIONS, "Sent TaskID(id) to BindServer");
|
||||
} catch (IOException e) {
|
||||
throw new Failure("Caught IOException while sending TaskID(id) to BindServer:\n\t"
|
||||
+ e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if thread is connected to <code>BindServer</code>.
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return (connection != null && connection.isConnected());
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to </code>BindServer</code>.
|
||||
*/
|
||||
public synchronized void sendCommand(Object command) throws IOException {
|
||||
connection.writeObject(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive response from <code>BindServer</code>.
|
||||
*/
|
||||
public Object getReply() {
|
||||
synchronized (replies) {
|
||||
while (replies.isEmpty()) {
|
||||
if (!isConnected()) {
|
||||
throw new Failure("No reply from BindServer: connection lost");
|
||||
}
|
||||
try {
|
||||
replies.wait(TRY_DELAY);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace(getOutStream());
|
||||
throw new Failure("Thread interrupted while waiting for reply from BindServer:\n\t"
|
||||
+ e);
|
||||
}
|
||||
}
|
||||
Object reply = replies.removeFirst();
|
||||
if (reply == null) {
|
||||
throw new Failure("No reply from BindServer: connection lost");
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add response object to the list of received responses.
|
||||
*/
|
||||
private void addReply(BindServer.Response reply) {
|
||||
synchronized (replies) {
|
||||
replies.add(reply);
|
||||
replies.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read packets from <code>BindServer<code> connection and
|
||||
* notify waiting thread if response or IOPipe message received.
|
||||
* Received lines of redirected streams are put into log.
|
||||
*/
|
||||
public void run() {
|
||||
trace(TRACE_LEVEL_THREADS, "BindServerListener thread started");
|
||||
try {
|
||||
for (;;) {
|
||||
Object reply = connection.readObject();
|
||||
if (reply == null) {
|
||||
break;
|
||||
} else if (reply instanceof BindServer.Disconnect) {
|
||||
reply = null;
|
||||
trace(TRACE_LEVEL_ACTIONS, "Packet is Disconnect: close connection");
|
||||
break;
|
||||
} else if (reply instanceof BindServer.RedirectedStream) {
|
||||
BindServer.RedirectedStream castedReply = (BindServer.RedirectedStream)reply;
|
||||
trace(TRACE_LEVEL_ACTIONS, "Packet is RedirectedStream: put message into log");
|
||||
log.println(castedReply.line);
|
||||
} else if (reply instanceof BindServer.Response) {
|
||||
BindServer.Response castedReply = (BindServer.Response)reply;
|
||||
trace(TRACE_LEVEL_ACTIONS, "Packet is reply: notify all threads waiting for reply");
|
||||
addReply(castedReply);
|
||||
} else {
|
||||
trace(TRACE_LEVEL_ACTIONS, "Packet is unknown: throw Failure");
|
||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(getOutStream());
|
||||
complain("Caught exception while reading packets from BindServer:\n\t" + e);
|
||||
} finally {
|
||||
closeConnection();
|
||||
addReply(null);
|
||||
trace(TRACE_LEVEL_THREADS, "BindServerListener thread finished");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send Disconnect command to </code>BindServer</code>.
|
||||
*/
|
||||
public void disconnect() {
|
||||
if (connection == null) return;
|
||||
try {
|
||||
sendCommand(new BindServer.Disconnect());
|
||||
} catch (IOException e) {
|
||||
display("Caught IOException while requesting disconnection with BindServer");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close socket connection.
|
||||
*/
|
||||
public void closeConnection() {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for thread finished in the specified timeout or interrupt it.
|
||||
*/
|
||||
public void waitForThread(long millis) {
|
||||
DebugeeBinder.waitForThread(this, millis, logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this thread by waiting for it finishes or interrupt it
|
||||
* and close socket connection.
|
||||
*/
|
||||
public void close() {
|
||||
disconnect();
|
||||
waitForThread(DebugeeBinder.THREAD_TIMEOUT);
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
} // BindServerListener
|
||||
|
||||
} // DebugeeBinder
|
||||
|
@ -74,8 +74,8 @@ abstract public class DebugeeProcess {
|
||||
/** Argument handler from binder. */
|
||||
protected DebugeeArgumentHandler argumentHandler = null;
|
||||
|
||||
/** Need or not to check debuggee process termination at exit. */
|
||||
protected boolean checkTermination = false;
|
||||
/** Need or not to check debuggee process termination. */
|
||||
private boolean checkTermination = true;
|
||||
|
||||
/** Debugee VM process or <i>null</i> if not available. */
|
||||
protected Process process = null;
|
||||
@ -164,26 +164,50 @@ abstract public class DebugeeProcess {
|
||||
// --------------------------------------------------- //
|
||||
|
||||
/** Wait until the debugee VM shutdown or crash. */
|
||||
abstract protected int waitForDebugee () throws InterruptedException;
|
||||
protected int waitForDebugee() throws InterruptedException {
|
||||
return process.waitFor();
|
||||
}
|
||||
|
||||
/** Kill the debugee VM. */
|
||||
abstract protected void killDebugee ();
|
||||
protected void killDebugee() {
|
||||
if (!terminated()) {
|
||||
log.display("Killing debugee VM process");
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/** Check whether the debugee VM has been terminated. */
|
||||
abstract public boolean terminated ();
|
||||
public boolean terminated() {
|
||||
if (process == null)
|
||||
return true;
|
||||
|
||||
try {
|
||||
int value = process.exitValue();
|
||||
return true;
|
||||
} catch (IllegalThreadStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the debugee VM exit status. */
|
||||
abstract public int getStatus ();
|
||||
public int getStatus() {
|
||||
return process.exitValue();
|
||||
}
|
||||
|
||||
/** Get a pipe to write to the debugee's stdin stream. */
|
||||
abstract protected OutputStream getInPipe ();
|
||||
protected OutputStream getInPipe() {
|
||||
return process.getOutputStream();
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stdout stream. */
|
||||
abstract protected InputStream getOutPipe ();
|
||||
protected InputStream getOutPipe() {
|
||||
return process.getInputStream();
|
||||
}
|
||||
|
||||
/** Get a pipe to read the debugee's stderr stream. */
|
||||
abstract protected InputStream getErrPipe ();
|
||||
|
||||
protected InputStream getErrPipe() {
|
||||
return process.getErrorStream();
|
||||
}
|
||||
// --------------------------------------------------- //
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user