Skip to content

Commit

Permalink
8213714: AttachingConnector/attach/attach001 failed due to "bind fail…
Browse files Browse the repository at this point in the history
…ed: Address already in use"

Reviewed-by: sspitsyn, cjplummer
  • Loading branch information
Alex Menkov committed Aug 10, 2021
1 parent 66d1faa commit b62e742
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 83 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, 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
Expand Down Expand Up @@ -34,6 +34,7 @@
import java.util.List;
import java.util.Map;

import jdk.test.lib.JDWP;
import nsk.share.*;
import nsk.share.jpda.*;
import nsk.share.jdi.*;
Expand Down Expand Up @@ -69,9 +70,6 @@ public static int run(String argv[], PrintStream out) {
}

private int runIt(String argv[], PrintStream out) {
String port;
String listenPort;
Process proc;
ArgumentHandler argHandler = new ArgumentHandler(argv);

// pass if "com.sun.jdi.SocketAttach" is not implemented
Expand All @@ -96,19 +94,17 @@ private int runIt(String argv[], PrintStream out) {
long timeout = argHandler.getWaitTime() * 60 * 1000;
attempts = (int)(timeout / delay);

port = argHandler.getTransportPort();
listenPort = argHandler.getTransportPort();

String java = argHandler.getLaunchExecPath()
+ " " + argHandler.getLaunchOptions();
String cmd = java +
" -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=" +
listenPort + " " + DEBUGEE_CLASS;
String cmd = java
+ " -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,address=0"
+ " " + DEBUGEE_CLASS;

Binder binder = new Binder(argHandler, log);
log.display("command: " + cmd);
Debugee debugee = binder.startLocalDebugee(cmd);
debugee.redirectOutput(log);
JDWP.ListenAddress listenAddress = debugee.redirectOutputAndDetectListeningAddress(log);
String port = listenAddress.address();

if ((vm = attachTarget(argHandler.getTestHost(), port)) == null) {
log.complain("TEST: Unable to attach the debugee VM");
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2021, 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
Expand Down Expand Up @@ -34,6 +34,7 @@
import java.util.List;
import java.util.Map;

import jdk.test.lib.JDWP;
import nsk.share.*;
import nsk.share.jpda.*;
import nsk.share.jdi.*;
Expand Down Expand Up @@ -69,9 +70,6 @@ public static int run(String argv[], PrintStream out) {
}

private int runIt(String argv[], PrintStream out) {
String port;
String listenPort;
Process proc;
ArgumentHandler argHandler = new ArgumentHandler(argv);

// pass if "com.sun.jdi.SocketAttach" is not implemented
Expand All @@ -96,19 +94,17 @@ private int runIt(String argv[], PrintStream out) {
long timeout = argHandler.getWaitTime() * 60 * 1000;
attempts = (int)(timeout / delay);

port = argHandler.getTransportPort();
listenPort = argHandler.getTransportPort();

String java = argHandler.getLaunchExecPath()
+ " " + argHandler.getLaunchOptions();
String cmd = java +
" -Xdebug -Xnoagent -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=" +
listenPort + " " + DEBUGEE_CLASS;
String cmd = java
+ " -Xdebug -Xnoagent -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0"
+ " " + DEBUGEE_CLASS;

Binder binder = new Binder(argHandler, log);
log.display("command: " + cmd);
Debugee debugee = binder.startLocalDebugee(cmd);
debugee.redirectOutput(log);
JDWP.ListenAddress listenAddress = debugee.redirectOutputAndDetectListeningAddress(log);
String port = listenAddress.address();

if ((vm = attachTarget(argHandler.getTestHost(), port)) == null) {
log.complain("TEST: Unable to attach the debugee VM");
Expand Down
62 changes: 23 additions & 39 deletions test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java
Expand Up @@ -24,20 +24,17 @@
package nsk.share;

import java.io.*;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;

/**
* This class implements a thread transfering bytes from
* a given InputStream to a given OutputStream.
*/
public class IORedirector extends Thread {
private BufferedReader bin = null;
private PrintStream pout = null;
private Log log = null;

/**
* Few symbols to precede every text line being redirected.
*/
private String prefix = "";
private List<Consumer<String>> processors = new LinkedList<>();

/**
* Input and output streams must be specified.
Expand All @@ -54,10 +51,16 @@ private IORedirector() {
* @see #IORedirector(BufferedReader,Log,String)
*/
@Deprecated
public IORedirector(InputStream in, OutputStream out) {
public IORedirector(InputStream in, OutputStream out, String prefix) {
this();
bin = new BufferedReader(new InputStreamReader(in));
pout = new PrintStream(out);
PrintStream pout = new PrintStream(out);
addProcessor(s -> {
synchronized (pout) {
pout.println(prefix + s);
pout.flush();
}
});
}

/**
Expand All @@ -67,16 +70,16 @@ public IORedirector(InputStream in, OutputStream out) {
*/
public IORedirector(BufferedReader in, Log log, String prefix) {
this();
this.prefix = prefix;
this.bin = in;
this.log = log;
addProcessor(s -> log.println(prefix + s));
}

/**
* Set the prefix for redirected messages;
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
public void addProcessor(Consumer<String> lineProcessor) {
processors.add(lineProcessor);
}

private void processLine(String line) {
processors.stream().forEach(processor -> processor.accept(line));
}

private boolean cancelled = false;
Expand Down Expand Up @@ -104,39 +107,20 @@ public void cancel () {
*/
public void run () {
started = true;
String logPrefix = "IORedirector-" + prefix;
if (bin == null || (pout == null && log == null))
if (bin == null || processors.isEmpty()) {
return;
}
try {
while (!cancelled) {
String line = bin.readLine();
if (line == null)
break; //EOF
String message = prefix + line;
if (log != null) {
// It's synchronized and auto-flushed:
log.println(message);
} else if (pout != null) {
synchronized (pout) {
pout.println(message);
pout.flush();
}
}
processLine(line);
}
} catch (IOException e) {
// e.printStackTrace(log.getOutStream());
String msg = "# WARNING: Caught IOException while redirecting output stream:\n\t" + e;
if (log != null) {
log.println(msg);
} else if (pout != null) {
synchronized (pout) {
pout.println(msg);
pout.flush();
}
} else {
System.err.println(msg);
System.err.flush();
}
processLine(msg);
};
stopped = true;
}
Expand Down
78 changes: 56 additions & 22 deletions test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java
Expand Up @@ -23,9 +23,11 @@

package nsk.share.jpda;

import jdk.test.lib.JDWP;
import nsk.share.*;
import java.io.*;
import java.net.*;
import java.util.function.Consumer;

/**
* This class is used to control debugee VM process.
Expand Down Expand Up @@ -302,8 +304,7 @@ final public InputStream getStderr () {

/**
* Start thread redirecting the debugee's stdout to the
* given <code>out</code> stream. If the debugee's stdout
* was already redirected, the TestBug exception is thrown.
* given <code>out</code> stream.
*
* @deprecated Use redirectStdout(Log, String) instead.
*/
Expand All @@ -312,35 +313,36 @@ public void redirectStdout(OutputStream out) {
if (stdoutRedirector != null) {
return;
}
// throw new TestBug("Debugee's stdout is already redirected");
stdoutRedirector = new IORedirector(getOutPipe(),out);
stdoutRedirector.setPrefix(DEBUGEE_STDOUT_LOG_PREFIX);
stdoutRedirector = new IORedirector(getOutPipe(), out, DEBUGEE_STDOUT_LOG_PREFIX);
stdoutRedirector.setName("IORedirector for stdout");
stdoutRedirector.setDaemon(true);
stdoutRedirector.start();
}

/**
* Start thread redirecting the debugee's stdout to the
* given <code>Log</code>. If the debugee's stdout
* was already redirected, the TestBug exception is thrown.
* given <code>Log</code>.
*/
public void redirectStdout(Log log, String prefix) {
redirectStdout(log, prefix, null);
}

private void redirectStdout(Log log, String prefix, Consumer<String> stdoutProcessor) {
if (stdoutRedirector != null) {
// stdoutRedirector.setPrefix(prefix);
return;
// throw new TestBug("the debugee's stdout is already redirected");
}
stdoutRedirector = new IORedirector(new BufferedReader(new InputStreamReader(getOutPipe())), log, prefix);
if (stdoutProcessor != null) {
stdoutRedirector.addProcessor(stdoutProcessor);
}
stdoutRedirector.setName("IORedirector for stdout");
stdoutRedirector.setDaemon(true);
stdoutRedirector.start();
}

/**
* Start thread redirecting the debugee's stderr to the
* given <code>err</code> stream. If the debugee's stderr
* was already redirected, the TestBug exception is thrown.
* given <code>err</code> stream.
*
* @deprecated Use redirectStderr(Log, String) instead.
*/
Expand All @@ -349,24 +351,19 @@ public void redirectStderr(OutputStream err) {
if (stderrRedirector != null) {
return;
}
// throw new TestBug("Debugee's stderr is already redirected");
stderrRedirector = new IORedirector(getErrPipe(),err);
stderrRedirector.setPrefix(DEBUGEE_STDERR_LOG_PREFIX);
stderrRedirector = new IORedirector(getErrPipe(), err, DEBUGEE_STDERR_LOG_PREFIX);
stdoutRedirector.setName("IORedirector for stderr");
stderrRedirector.setDaemon(true);
stderrRedirector.start();
}

/**
* Start thread redirecting the debugee's stderr to the
* given <code>Log</code>. If the debugee's stderr
* was already redirected, the TestBug exception is thrown.
* given <code>Log</code>.
*/
public void redirectStderr(Log log, String prefix) {
if (stderrRedirector != null) {
// stderrRedirector.setPrefix(prefix);
return;
// throw new TestBug("Debugee's stderr is already redirected");
}
stderrRedirector = new IORedirector(new BufferedReader(new InputStreamReader(getErrPipe())), log, prefix);
stdoutRedirector.setName("IORedirector for stderr");
Expand All @@ -377,13 +374,50 @@ public void redirectStderr(Log log, String prefix) {
/**
* Start thread redirecting the debugee's stdout/stderr to the
* given <code>Log</code> using standard prefixes.
* If the debugee's stdout/stderr were already redirected,
* the TestBug exception is thrown.
*/
public void redirectOutput(Log log) {
redirectStdout(log, "debugee.stdout> ");
redirectStderr(log, "debugee.stderr> ");
redirectStdout(log, DEBUGEE_STDOUT_LOG_PREFIX);
redirectStderr(log, DEBUGEE_STDERR_LOG_PREFIX);
}

/**
* Starts redirecting of the debugee's stdout/stderr to the
* given <code>Log</code> using standard prefixes
* and detects listening address from the debuggee stdout.
*/
public JDWP.ListenAddress redirectOutputAndDetectListeningAddress(Log log) {
JDWP.ListenAddress listenAddress[] = new JDWP.ListenAddress[1];
Consumer<String> stdoutProcessor = line -> {
JDWP.ListenAddress addr = JDWP.parseListenAddress(line);
if (addr != null) {
synchronized (listenAddress) {
listenAddress[0] = addr;
listenAddress.notifyAll();
}
}
};

redirectStdout(log, DEBUGEE_STDOUT_LOG_PREFIX, stdoutProcessor);
redirectStderr(log, DEBUGEE_STDERR_LOG_PREFIX);

synchronized (listenAddress) {
while (!terminated() && listenAddress[0] == null) {
try {
listenAddress.wait(500);
} catch (InterruptedException e) {
// ignore
}
}
}
if (terminated()) {
throw new Failure("Failed to detect debuggee listening port");
}

log.display("Debuggee is listening on port " + listenAddress[0].address());

return listenAddress[0];
}

// --------------------------------------------------- //

/**
Expand Down

3 comments on commit b62e742

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GoeLin
Copy link
Member

@GoeLin GoeLin commented on b62e742 Mar 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/backport jdk17u-dev

@openjdk
Copy link

@openjdk openjdk bot commented on b62e742 Mar 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GoeLin the backport was successfully created on the branch backport-GoeLin-b62e7420 in my personal fork of openjdk/jdk17u-dev. To create a pull request with this backport targeting openjdk/jdk17u-dev:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit b62e7420 from the openjdk/jdk repository.

The commit being backported was authored by Alex Menkov on 10 Aug 2021 and was reviewed by Serguei Spitsyn and Chris Plummer.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk17u-dev:

$ git fetch https://github.com/openjdk-bots/jdk17u-dev.git backport-GoeLin-b62e7420:backport-GoeLin-b62e7420
$ git checkout backport-GoeLin-b62e7420
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk17u-dev.git backport-GoeLin-b62e7420

Please sign in to comment.