Skip to content

Commit

Permalink
8318736: com/sun/jdi/JdwpOnThrowTest.java failed with "transport erro…
Browse files Browse the repository at this point in the history
…r 202: bind failed: Address already in use"

Reviewed-by: amenkov
  • Loading branch information
parttimenerd committed Nov 3, 2023
1 parent 81db172 commit 1a21c1a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 38 deletions.
15 changes: 3 additions & 12 deletions test/jdk/com/sun/jdi/JdwpOnThrowTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,11 @@ public class JdwpOnThrowTest {
private static AttachingConnector attachingConnector;

public static void main(String[] args) throws Exception {
int port = findFreePort();
try (Debuggee debuggee = Debuggee.launcher("ThrowCaughtException").setAddress("localhost:" + port)
.enableOnThrow("Ex", "Start").setSuspended(true).launch()) {
try (Debuggee debuggee = Debuggee.launcher("ThrowCaughtException")
.enableOnThrow("Ex").setSuspended(true).launch()) {
VirtualMachine vm = null;
try {
vm = attach("localhost", "" + port);
vm = attach("localhost", debuggee.getAddress());
EventQueue queue = vm.eventQueue();
log("Waiting for exception event");
long start = System.currentTimeMillis();
Expand Down Expand Up @@ -110,14 +109,6 @@ private static void verifyExceptionEvent(ExceptionEvent ex) throws Exception {
}
}

private static int findFreePort() {
try (ServerSocket socket = new ServerSocket(0)) {
return socket.getLocalPort();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private static VirtualMachine attach(String address, String port) throws IOException {
if (attachingConnector == null) {
attachingConnector = (AttachingConnector)getConnector(ATTACH_CONNECTOR);
Expand Down
55 changes: 29 additions & 26 deletions test/jdk/com/sun/jdi/lib/jdb/Debuggee.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -69,8 +72,7 @@ public static class Launcher {
private String address = null;
private boolean suspended = true;
private String onthrow = "";
private boolean waitForPortPrint = true;
private String expectedOutputBeforeThrow = "";
private static final String LAUNCH_ECHO_STRING = "Listen Args:";

private Launcher(String mainClass) {
this.mainClass = mainClass;
Expand Down Expand Up @@ -103,11 +105,8 @@ public Launcher setSuspended(boolean value) {
return this;
}

// required to pass non null port with address and emit string before the throw
public Launcher enableOnThrow(String value, String expectedOutputBeforeThrow) {
this.onthrow = value;
this.waitForPortPrint = false;
this.expectedOutputBeforeThrow = expectedOutputBeforeThrow;
public Launcher enableOnThrow(String exceptionClassName) {
this.onthrow = exceptionClassName;
return this;
}

Expand All @@ -116,7 +115,7 @@ public ProcessBuilder prepare() {
if (vmOptions != null) {
debuggeeArgs.add(vmOptions);
}
String onthrowArgs = onthrow.isEmpty() ? "" : ",onthrow=" + onthrow + ",launch=exit";
String onthrowArgs = onthrow.isEmpty() ? "" : ",onthrow=" + onthrow + ",launch=echo " + LAUNCH_ECHO_STRING;
debuggeeArgs.add("-agentlib:jdwp=transport=" + transport
+ (address == null ? "" : ",address=" + address)
+ ",server=y,suspend=" + (suspended ? "y" : "n")
Expand All @@ -127,33 +126,38 @@ public ProcessBuilder prepare() {
}

public Debuggee launch(String name) {
return new Debuggee(prepare(), name, waitForPortPrint, expectedOutputBeforeThrow);
return new Debuggee(prepare(), name,
onthrow.isEmpty() ?
JDWP::parseListenAddress :
Launcher::parseLaunchEchoListenAddress
);
}
public Debuggee launch() {
return launch("debuggee");
}
}

// starts the process, waits for "Listening for transport" output and detects transport/address
private Debuggee(ProcessBuilder pb, String name, boolean waitForPortPrint, String expectedOutputBeforeThrow) {
JDWP.ListenAddress[] listenAddress = new JDWP.ListenAddress[1];
if (!waitForPortPrint) {
try {
p = ProcessTools.startProcess(name, pb, s -> {output.add(s);}, s -> {
return s.equals(expectedOutputBeforeThrow);
}, 30, TimeUnit.SECONDS);
} catch (IOException | InterruptedException | TimeoutException ex) {
throw new RuntimeException("failed to launch debuggee", ex);
/**
* Parses debuggee output to get listening transport and address, printed by `launch=echo`.
* Returns null if the string specified does not contain required info.
*/
private static JDWP.ListenAddress parseLaunchEchoListenAddress(String debuggeeOutput) {
Pattern listenRegexp = Pattern.compile(LAUNCH_ECHO_STRING + " \\b(.+)\\b \\b(.+)\\b");
Matcher m = listenRegexp.matcher(debuggeeOutput);
if (m.find()) {
return new JDWP.ListenAddress(m.group(1), m.group(2));
}
transport = null;
address = null;
return;
return null;
}
}

// starts the process, waits until the provided addressDetector detects transport/address from the process output
private Debuggee(ProcessBuilder pb, String name, Function<String, JDWP.ListenAddress> addressDetector) {
JDWP.ListenAddress[] listenAddress = new JDWP.ListenAddress[1];
try {
p = ProcessTools.startProcess(name, pb,
s -> output.add(s), // output consumer
s -> { // warm-up predicate
listenAddress[0] = JDWP.parseListenAddress(s);
s -> {
listenAddress[0] = addressDetector.apply(s);
return listenAddress[0] != null;
},
30, TimeUnit.SECONDS);
Expand Down Expand Up @@ -211,5 +215,4 @@ public void close() throws IOException {
p.destroy();
}
}

}

0 comments on commit 1a21c1a

Please sign in to comment.