Skip to content

Commit a209ed0

Browse files
committed
8263670: pmap and pstack in jhsdb do not work on debug server
Reviewed-by: cjplummer, sspitsyn
1 parent 38e0a58 commit a209ed0

File tree

10 files changed

+164
-44
lines changed

10 files changed

+164
-44
lines changed

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -444,16 +444,12 @@ private void setupVM() {
444444
db.getJShortType().getSize());
445445
}
446446

447-
if (!isServer) {
448-
// Do not initialize the VM on the server (unnecessary, since it's
449-
// instantiated on the client)
450-
try {
451-
VM.initialize(db, debugger);
452-
} catch (DebuggerException e) {
453-
throw (e);
454-
} catch (Exception e) {
455-
throw new DebuggerException(e);
456-
}
447+
try {
448+
VM.initialize(db, debugger);
449+
} catch (DebuggerException e) {
450+
throw (e);
451+
} catch (Exception e) {
452+
throw new DebuggerException(e);
457453
}
458454
}
459455

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
2525
package sun.jvm.hotspot.debugger.remote;
2626

2727
import java.rmi.*;
28+
import java.util.*;
2829

2930
import sun.jvm.hotspot.debugger.*;
3031

@@ -76,4 +77,8 @@ public boolean areThreadsEqual(long addrOrId1, boolean isAddress1,
7677
long addrOrId2, boolean isAddress2) throws RemoteException;
7778
public int getThreadHashCode(long addrOrId, boolean isAddress) throws RemoteException;
7879
public long[] getThreadIntegerRegisterSet(long addrOrId, boolean isAddress) throws RemoteException;
80+
81+
public default String execCommandOnServer(String command, Map<String, Object> options) throws RemoteException {
82+
throw new DebuggerException("Command execution is not supported");
83+
}
7984
}

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -415,4 +415,12 @@ public ReadResult readBytesFromProcess(long address, long numBytes) {
415415
public void writeBytesToProcess(long a, long b, byte[] c) {
416416
throw new DebuggerException("Unimplemented!");
417417
}
418+
419+
public String execCommandOnServer(String command, Map<String, Object> options) {
420+
try {
421+
return remoteDebugger.execCommandOnServer(command, options);
422+
} catch (RemoteException e) {
423+
throw new DebuggerException(e);
424+
}
425+
}
418426
}

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,18 +24,21 @@
2424

2525
package sun.jvm.hotspot.debugger.remote;
2626

27+
import java.io.*;
2728
import java.rmi.*;
2829
import java.rmi.server.*;
30+
import java.util.*;
2931

3032
import sun.jvm.hotspot.debugger.*;
33+
import sun.jvm.hotspot.tools.*;
3134

3235
/** The implementation of the RemoteDebugger interface. This
3336
delegates to a local debugger */
3437

3538
public class RemoteDebuggerServer extends UnicastRemoteObject
3639
implements RemoteDebugger {
3740

38-
private transient Debugger debugger;
41+
private transient JVMDebugger debugger;
3942

4043
/** This is the required no-arg constructor */
4144
public RemoteDebuggerServer() throws RemoteException {
@@ -44,14 +47,14 @@ public RemoteDebuggerServer() throws RemoteException {
4447

4548
/** This is the constructor used on the machine where the debuggee
4649
process lies that accepts an RMI connector port */
47-
public RemoteDebuggerServer(Debugger debugger, int port) throws RemoteException {
50+
public RemoteDebuggerServer(JVMDebugger debugger, int port) throws RemoteException {
4851
super(port);
4952
this.debugger = debugger;
5053
}
5154

5255
/** This is the constructor used on the machine where the debuggee
5356
process lies */
54-
public RemoteDebuggerServer(Debugger debugger) throws RemoteException {
57+
public RemoteDebuggerServer(JVMDebugger debugger) throws RemoteException {
5558
this(debugger, 0);
5659
}
5760

@@ -175,4 +178,23 @@ private ThreadProxy getThreadProxy(long addrOrId, boolean isAddress) throws Debu
175178
return debugger.getThreadForThreadId(addrOrId);
176179
}
177180
}
181+
182+
@Override
183+
public String execCommandOnServer(String command, Map<String, Object> options) throws RemoteException {
184+
ByteArrayOutputStream bout = new ByteArrayOutputStream();
185+
try (var out = new PrintStream(bout)) {
186+
if (command.equals("pmap")) {
187+
(new PMap(debugger)).run(out, debugger);
188+
} else if (command.equals("pstack")) {
189+
PStack pstack = new PStack(debugger);
190+
pstack.setVerbose(false);
191+
pstack.setConcurrentLocks((boolean)options.get("concurrentLocks"));
192+
pstack.run(out, debugger);
193+
} else {
194+
throw new DebuggerException(command + " is not supported in this debugger");
195+
}
196+
}
197+
198+
return bout.toString();
199+
}
178200
}

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PMap.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import sun.jvm.hotspot.*;
3030
import sun.jvm.hotspot.debugger.*;
3131
import sun.jvm.hotspot.debugger.cdbg.*;
32+
import sun.jvm.hotspot.debugger.remote.*;
3233
import sun.jvm.hotspot.utilities.PlatformInfo;
3334

3435
public class PMap extends Tool {
@@ -77,7 +78,7 @@ public void run(PrintStream out, Debugger dbg) {
7778
}
7879
} else {
7980
if (getDebugeeType() == DEBUGEE_REMOTE) {
80-
out.println("remote configuration is not yet implemented");
81+
out.print(((RemoteDebuggerClient)dbg).execCommandOnServer("pmap", null));
8182
} else {
8283
out.println("not yet implemented (debugger does not support CDebugger)!");
8384
}

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import sun.jvm.hotspot.interpreter.*;
3232
import sun.jvm.hotspot.debugger.*;
3333
import sun.jvm.hotspot.debugger.cdbg.*;
34+
import sun.jvm.hotspot.debugger.remote.*;
3435
import sun.jvm.hotspot.oops.*;
3536
import sun.jvm.hotspot.runtime.*;
3637
import sun.jvm.hotspot.utilities.PlatformInfo;
@@ -197,7 +198,7 @@ public void run(PrintStream out, Debugger dbg) {
197198
} // for threads
198199
} else {
199200
if (getDebugeeType() == DEBUGEE_REMOTE) {
200-
out.println("remote configuration is not yet implemented");
201+
out.print(((RemoteDebuggerClient)dbg).execCommandOnServer("pstack", Map.of("concurrentLocks", concurrentLocks)));
201202
} else {
202203
out.println("not yet implemented (debugger does not support CDebugger)!");
203204
}
@@ -289,4 +290,12 @@ private String[] getJavaNames(ThreadProxy th, Address fp) {
289290
System.arraycopy(names.toArray(), 0, res, 0, res.length);
290291
return res;
291292
}
293+
294+
public void setVerbose(boolean verbose) {
295+
this.verbose = verbose;
296+
}
297+
298+
public void setConcurrentLocks(boolean concurrentLocks) {
299+
this.concurrentLocks = concurrentLocks;
300+
}
292301
}

test/hotspot/jtreg/serviceability/sa/sadebugd/ClhsdbAttachToDebugServer.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,7 @@ public class ClhsdbAttachToDebugServer {
4545

4646
public static void main(String[] args) throws Exception {
4747
SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
48-
49-
if (SATestUtils.needsPrivileges()) {
50-
// This tests has issues if you try adding privileges on OSX. The debugd process cannot
51-
// be killed if you do this (because it is a root process and the test is not), so the destroy()
52-
// call fails to do anything, and then waitFor() will time out. If you try to manually kill it with
53-
// a "sudo kill" command, that seems to work, but then leaves the LingeredApp it was
54-
// attached to in a stuck state for some unknown reason, causing the stopApp() call
55-
// to timeout. For that reason we don't run this test when privileges are needed. Note
56-
// it does appear to run fine as root, so we still allow it to run on OSX when privileges
57-
// are not required.
58-
throw new SkippedException("Cannot run this test on OSX if adding privileges is required.");
59-
}
48+
SATestUtils.validateSADebugDPrivileges();
6049

6150
System.out.println("Starting ClhsdbAttachToDebugServer test");
6251

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2021 NTT DATA.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
import jdk.test.lib.JDKToolLauncher;
26+
import jdk.test.lib.apps.LingeredApp;
27+
import jdk.test.lib.process.OutputAnalyzer;
28+
import jdk.test.lib.SA.SATestUtils;
29+
30+
import jtreg.SkippedException;
31+
32+
/**
33+
* @test
34+
* @bug 8263670
35+
* @requires vm.hasSA
36+
* @requires (os.family != "windows") & (os.family != "mac")
37+
* @library /test/lib
38+
* @run main/othervm PmapOnDebugdTest
39+
*/
40+
41+
public class PmapOnDebugdTest {
42+
43+
public static void main(String[] args) throws Exception {
44+
SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
45+
SATestUtils.validateSADebugDPrivileges();
46+
47+
LingeredApp theApp = null;
48+
DebugdUtils debugd = null;
49+
try {
50+
theApp = LingeredApp.startApp();
51+
System.out.println("Started LingeredApp with pid " + theApp.getPid());
52+
debugd = new DebugdUtils(null);
53+
debugd.attach(theApp.getPid());
54+
55+
JDKToolLauncher jhsdbLauncher = JDKToolLauncher.createUsingTestJDK("jhsdb");
56+
jhsdbLauncher.addToolArg("jmap");
57+
jhsdbLauncher.addToolArg("--connect");
58+
jhsdbLauncher.addToolArg("localhost");
59+
60+
Process jhsdb = (SATestUtils.createProcessBuilder(jhsdbLauncher)).start();
61+
OutputAnalyzer out = new OutputAnalyzer(jhsdb);
62+
63+
jhsdb.waitFor();
64+
System.out.println(out.getStdout());
65+
System.err.println(out.getStderr());
66+
67+
out.stderrShouldBeEmptyIgnoreDeprecatedWarnings();
68+
out.shouldMatch("^0x[0-9a-f]+.+libjvm\\.so$"); // Find libjvm from output
69+
out.shouldHaveExitValue(0);
70+
71+
// This will detect most SA failures, including during the attach.
72+
out.shouldNotMatch("^sun.jvm.hotspot.debugger.DebuggerException:.*$");
73+
} catch (SkippedException se) {
74+
throw se;
75+
} catch (Exception ex) {
76+
throw new RuntimeException("Test ERROR " + ex, ex);
77+
} finally {
78+
if (debugd != null) {
79+
debugd.detach();
80+
}
81+
LingeredApp.stopApp(theApp);
82+
}
83+
System.out.println("Test PASSED");
84+
}
85+
}

test/hotspot/jtreg/serviceability/sa/sadebugd/SADebugDTest.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -56,18 +56,7 @@ public class SADebugDTest {
5656

5757
public static void main(String[] args) throws Exception {
5858
SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work.
59-
60-
if (SATestUtils.needsPrivileges()) {
61-
// This tests has issues if you try adding privileges on OSX. The debugd process cannot
62-
// be killed if you do this (because it is a root process and the test is not), so the destroy()
63-
// call fails to do anything, and then waitFor() will time out. If you try to manually kill it with
64-
// a "sudo kill" command, that seems to work, but then leaves the LingeredApp it was
65-
// attached to in a stuck state for some unknown reason, causing the stopApp() call
66-
// to timeout. For that reason we don't run this test when privileges are needed. Note
67-
// it does appear to run fine as root, so we still allow it to run on OSX when privileges
68-
// are not required.
69-
throw new SkippedException("Cannot run this test on OSX if adding privileges is required.");
70-
}
59+
SATestUtils.validateSADebugDPrivileges();
7160
runTests();
7261
}
7362

test/lib/jdk/test/lib/SA/SATestUtils.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -207,4 +207,20 @@ private static boolean canPtraceAttachLinux() throws IOException {
207207
// Otherwise expect to be permitted:
208208
return true;
209209
}
210+
211+
/**
212+
* This tests has issues if you try adding privileges on OSX. The debugd process cannot
213+
* be killed if you do this (because it is a root process and the test is not), so the destroy()
214+
* call fails to do anything, and then waitFor() will time out. If you try to manually kill it with
215+
* a "sudo kill" command, that seems to work, but then leaves the LingeredApp it was
216+
* attached to in a stuck state for some unknown reason, causing the stopApp() call
217+
* to timeout. For that reason we don't run this test when privileges are needed. Note
218+
* it does appear to run fine as root, so we still allow it to run on OSX when privileges
219+
* are not required.
220+
*/
221+
public static void validateSADebugDPrivileges() {
222+
if (needsPrivileges()) {
223+
throw new SkippedException("Cannot run this test on OSX if adding privileges is required.");
224+
}
225+
}
210226
}

0 commit comments

Comments
 (0)