8260296: SA's dumpreplaydata fails

Reviewed-by: kvn, cjplummer, iignatyev
This commit is contained in:
Roland Westrelin 2021-02-05 09:33:54 +00:00
parent 07918995da
commit 3495febf51
20 changed files with 173 additions and 119 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@ -27,6 +27,9 @@
#include "ci/ciUtilities.inline.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
// Not inlined to preserve visibility of ciMetaData vtable symbol. Required by SA.
bool ciMetadata::is_classless() const { return false; }
// ------------------------------------------------------------------
// ciMetadata::print
//

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
@ -43,7 +43,7 @@ class ciMetadata: public ciBaseObject {
ciMetadata(): _metadata(NULL) {}
ciMetadata(Metadata* o): _metadata(o) {}
virtual bool is_classless() const { return false; }
virtual bool is_classless() const;
public:
bool is_loaded() const { return _metadata != NULL || is_classless(); }

View File

@ -1256,7 +1256,7 @@ void MethodData::initialize() {
object_size += extra_size + arg_data_size;
int parms_cell = ParametersTypeData::compute_cell_count(method());
// If we are profiling parameters, we reserver an area near the end
// If we are profiling parameters, we reserved an area near the end
// of the MDO after the slots for bytecodes (because there's no bci
// for method entry so they don't fit with the framework for the
// profiling of bytecodes). We store the offset within the MDO of

View File

@ -261,7 +261,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
nonstatic_field(Klass, _java_mirror, OopHandle) \
nonstatic_field(Klass, _modifier_flags, jint) \
nonstatic_field(Klass, _super, Klass*) \
volatile_nonstatic_field(Klass, _subklass, Klass*) \
volatile_nonstatic_field(Klass, _subklass, Klass*) \
nonstatic_field(Klass, _layout_helper, jint) \
nonstatic_field(Klass, _name, Symbol*) \
nonstatic_field(Klass, _access_flags, AccessFlags) \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -30,6 +30,7 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.types.Field;
import sun.jvm.hotspot.utilities.Observable;
import sun.jvm.hotspot.utilities.Observer;
@ -44,7 +45,7 @@ public class ciMethodData extends ciMetadata implements MethodDataInterface<ciKl
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ciMethodData");
origField = type.getAddressField("_orig");
origField = type.getField("_orig");
currentMileageField = new CIntField(type.getCIntegerField("_current_mileage"), 0);
argReturnedField = new CIntField(type.getCIntegerField("_arg_returned"), 0);
argStackField = new CIntField(type.getCIntegerField("_arg_stack"), 0);
@ -61,7 +62,7 @@ public class ciMethodData extends ciMetadata implements MethodDataInterface<ciKl
parametersTypeDataDi = new CIntField(typeMethodData.getCIntegerField("_parameters_type_data_di"), 0);
}
private static AddressField origField;
private static Field origField;
private static CIntField currentMileageField;
private static CIntField argReturnedField;
private static CIntField argStackField;
@ -106,8 +107,8 @@ public class ciMethodData extends ciMetadata implements MethodDataInterface<ciKl
public byte[] orig() {
// fetch the orig MethodData data between header and dataSize
Address base = getAddress().addOffsetTo(origField.getOffset());
byte[] result = new byte[MethodData.sizeofMethodDataOopDesc];
for (int i = 0; i < MethodData.sizeofMethodDataOopDesc; i++) {
byte[] result = new byte[(int)origField.getType().getSize()];
for (int i = 0; i < result.length; i++) {
result[i] = base.getJByteAt(i);
}
return result;
@ -116,7 +117,7 @@ public class ciMethodData extends ciMetadata implements MethodDataInterface<ciKl
public long[] data() {
// Read the data as an array of intptr_t elements
Address base = dataField.getValue(getAddress());
int elements = dataSize() / MethodData.cellSize;
int elements = (dataSize() + extraDataSize()) / MethodData.cellSize;
long[] result = new long[elements];
for (int i = 0; i < elements; i++) {
Address value = base.getAddressAt(i * MethodData.cellSize);
@ -148,8 +149,7 @@ public class ciMethodData extends ciMetadata implements MethodDataInterface<ciKl
}
ParametersTypeData<ciKlass,ciMethod> parametersTypeData() {
Address base = getAddress().addOffsetTo(origField.getOffset());
int di = (int)parametersTypeDataDi.getValue(base);
int di = (int)parametersTypeDataDi.getValue(getMetadata().getAddress());
if (di == -1 || di == -2) {
return null;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -81,9 +81,8 @@ public class DataLayout {
return data.getJShortAt(offset + at) & 0xffff;
}
int cellAt(int index) {
// Cells are intptr_t sized but only contain ints as raw values
return (int)data.getCIntegerAt(offset + cellOffset(index), MethodData.cellSize, false);
long cellAt(int index) {
return data.getCIntegerAt(offset + cellOffset(index), MethodData.cellSize, false);
}
public Address addressAt(int index) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, 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
@ -234,8 +234,8 @@ public class MethodData extends Metadata implements MethodDataInterface<Klass,Me
public void iterateFields(MetadataVisitor visitor) {
super.iterateFields(visitor);
visitor.doMetadata(method, true);
visitor.doCInt(size, true);
}
visitor.doCInt(size, true);
}
int dataSize() {
if (dataSize == null) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -51,7 +51,7 @@ public abstract class ProfileData {
}
// Low-level accessors for underlying data
int intptrAt(int index) {
long intptrAt(int index) {
//assert(0 <= index && index < cellCount(), "oob");
return data().cellAt(index);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 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
@ -48,17 +48,17 @@ public abstract class TypeEntries<K,M> {
final MethodDataInterface<K,M> methodData;
boolean wasNullSeen(int index) {
int v = pd.intptrAt(index);
long v = pd.intptrAt(index);
return (v & nullSeen) != 0;
}
boolean isTypeUnknown(int index) {
int v = pd.intptrAt(index);
long v = pd.intptrAt(index);
return (v & typeUnknown) != 0;
}
boolean isTypeNone(int index) {
int v = pd.intptrAt(index);
long v = pd.intptrAt(index);
return (v & typeMask) == 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -43,6 +43,7 @@ import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils;
import jdk.test.lib.util.CoreUtils;
public abstract class CiReplayBase {
public static final String REPLAY_FILE_NAME = "test_replay.txt";
@ -65,17 +66,27 @@ public abstract class CiReplayBase {
"-XX:MetaspaceSize=4m", "-XX:MaxMetaspaceSize=16m", "-XX:InitialCodeCacheSize=512k",
"-XX:ReservedCodeCacheSize=4m", "-XX:ThreadStackSize=512", "-XX:VMThreadStackSize=512",
"-XX:CompilerThreadStackSize=512", "-XX:ParallelGCThreads=1", "-XX:CICompilerCount=2",
"-Xcomp", "-XX:CICrashAt=1", "-XX:+DumpReplayDataOnError",
"-XX:+PreferInterpreterNativeStubs", "-XX:+PrintCompilation", REPLAY_FILE_OPTION};
"-XX:-BackgroundCompilation", "-XX:CompileCommand=inline,java.io.PrintStream::*",
"-XX:+IgnoreUnrecognizedVMOptions", "-XX:TypeProfileLevel=222", // extra profile data as a stress test
"-XX:CICrashAt=1", "-XX:+DumpReplayDataOnError",
"-XX:+PreferInterpreterNativeStubs", REPLAY_FILE_OPTION};
private static final String[] REPLAY_OPTIONS = new String[]{DISABLE_COREDUMP_ON_CRASH,
"-XX:+IgnoreUnrecognizedVMOptions", "-XX:TypeProfileLevel=222",
"-XX:+ReplayCompiles", REPLAY_FILE_OPTION};
protected final Optional<Boolean> runServer;
private static int dummy;
public static class TestMain {
public static void main(String[] args) {
// Do something because empty methods might not be called/compiled.
dummy = 42;
for (int i = 0; i < 20_000; i++) {
test(i);
}
}
static void test(int i) {
if ((i % 1000) == 0) {
System.out.println("Hello World!");
}
}
}
@ -103,7 +114,7 @@ public abstract class CiReplayBase {
public void runTest(boolean needCoreDump, String... args) {
cleanup();
if (generateReplay(needCoreDump)) {
if (generateReplay(needCoreDump, args)) {
testAction();
cleanup();
} else {
@ -143,11 +154,16 @@ public abstract class CiReplayBase {
options.addAll(Arrays.asList(REPLAY_GENERATION_OPTIONS));
options.addAll(Arrays.asList(vmopts));
options.add(needCoreDump ? ENABLE_COREDUMP_ON_CRASH : DISABLE_COREDUMP_ON_CRASH);
options.add(TestMain.class.getName());
if (needCoreDump) {
crashOut = ProcessTools.executeProcess(getTestJvmCommandlineWithPrefix(
RUN_SHELL_NO_LIMIT, options.toArray(new String[0])));
// CiReplayBase$TestMain needs to be quoted because of shell eval
options.add("-XX:CompileOnly='" + TestMain.class.getName() + "::test'");
options.add("'" + TestMain.class.getName() + "'");
crashOut = ProcessTools.executeProcess(
CoreUtils.addCoreUlimitCommand(
ProcessTools.createTestJvm(options.toArray(new String[0]))));
} else {
options.add("-XX:CompileOnly=" + TestMain.class.getName() + "::test");
options.add(TestMain.class.getName());
crashOut = ProcessTools.executeProcess(ProcessTools.createTestJvm(options));
}
crashOutputString = crashOut.getOutput();
@ -159,18 +175,8 @@ public abstract class CiReplayBase {
throw new Error("Can't create replay: " + t, t);
}
if (needCoreDump) {
String coreFileLocation = getCoreFileLocation(crashOutputString);
if (coreFileLocation == null) {
if (Platform.isOSX()) {
File coresDir = new File("/cores");
if (!coresDir.isDirectory() || !coresDir.canWrite()) {
return false;
}
}
throw new Error("Couldn't find core file location in: '" + crashOutputString + "'");
}
try {
Asserts.assertGT(new File(coreFileLocation).length(), 0L, "Unexpected core size");
String coreFileLocation = CoreUtils.getCoreFileLocation(crashOutputString, crashOut.pid());
Files.move(Paths.get(coreFileLocation), Paths.get(TEST_CORE_FILE_NAME));
} catch (IOException ioe) {
throw new Error("Can't move core file: " + ioe, ioe);
@ -250,48 +256,6 @@ public abstract class CiReplayBase {
}
}
// lets search few possible locations using process output and return existing location
private String getCoreFileLocation(String crashOutputString) {
Asserts.assertTrue(crashOutputString.contains(LOCATIONS_STRING),
"Output doesn't contain the location of core file, see crash.out");
String stringWithLocation = Arrays.stream(crashOutputString.split("\\r?\\n"))
.filter(str -> str.contains(LOCATIONS_STRING))
.findFirst()
.get();
stringWithLocation = stringWithLocation.substring(stringWithLocation
.indexOf(LOCATIONS_STRING) + LOCATIONS_STRING.length());
String coreWithPid;
if (stringWithLocation.contains("or ") && !Platform.isWindows()) {
Matcher m = Pattern.compile("or.* ([^ ]+[^\\)])\\)?").matcher(stringWithLocation);
if (!m.find()) {
throw new Error("Couldn't find path to core inside location string");
}
coreWithPid = m.group(1);
} else {
coreWithPid = stringWithLocation.trim();
}
if (new File(coreWithPid).exists()) {
return coreWithPid;
}
String justCore = Paths.get("core").toString();
if (new File(justCore).exists()) {
return justCore;
}
Path coreWithPidPath = Paths.get(coreWithPid);
String justFile = coreWithPidPath.getFileName().toString();
if (new File(justFile).exists()) {
return justFile;
}
Path parent = coreWithPidPath.getParent();
if (parent != null) {
String coreWithoutPid = parent.resolve("core").toString();
if (new File(coreWithoutPid).exists()) {
return coreWithoutPid;
}
}
return null;
}
private String[] getTestJvmCommandlineWithPrefix(String prefix, String... args) {
try {
String cmd = ProcessTools.getCommandLine(ProcessTools.createTestJvm(args));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -25,6 +25,8 @@ package compiler.ciReplay;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
@ -41,7 +43,19 @@ public class SABase extends CiReplayBase {
public static void main(String args[]) throws Exception {
checkSetLimits();
new SABase(args).runTest(/* needCoreDump = */ true, args);
SABase base = new SABase(args);
boolean c2 = base.runServer.orElseThrow(() -> new Error("runServer must be set"));
String[] extra = {};
if (Platform.isTieredSupported()) {
if (c2) {
// Replay produced on first compilation. We want that
// compilation delayed so profile data is produced.
extra = new String[] {"-XX:-TieredCompilation"};
} else {
extra = new String[] {"-XX:TieredStopAtLevel=1"};
}
}
base.runTest(/* needCoreDump = */ true, extra);
}
public SABase(String[] args) {
@ -96,19 +110,42 @@ public class SABase extends CiReplayBase {
File replay = new File(REPLAY_FILE_NAME);
Asserts.assertTrue(replay.exists() && replay.isFile() && replay.length() > 0,
"Replay data wasn't generated by SA");
// other than comment lines, content of 2 files should be identical
try {
FileInputStream rep = new FileInputStream(replay);
FileInputStream repCopy = new FileInputStream(REPLAY_FILE_COPY);
byte repBuffer[] = new byte[512];
byte repCopyBuffer[] = new byte[512];
boolean filesNotEqual = false;
while(rep.available() > 0 && !filesNotEqual) {
int count = rep.read(repBuffer);
int count2 = repCopy.read(repCopyBuffer);
filesNotEqual = count != count2 || Arrays.equals(repBuffer, repCopyBuffer);
BufferedReader rep = new BufferedReader(new FileReader(replay));
BufferedReader repCopy = new BufferedReader(new FileReader(REPLAY_FILE_COPY));
boolean failure = false;
while (true) {
String l1;
while ((l1 = rep.readLine()) != null) {
if (!l1.startsWith("#")) {
break;
}
}
String l2;
while ((l2 = repCopy.readLine()) != null) {
if (!l2.startsWith("#")) {
break;
}
}
if (l1 == null || l2 == null) {
if (l1 != null || l2 != null) {
System.out.println("Warning: replay files are not equal");
System.out.println("1: " + l1);
System.out.println("2: " + l2);
failure = true;
}
break;
}
if (!l1.equals(l2)) {
System.out.println("Warning: replay files are not equal");
System.out.println("1: " + l1);
System.out.println("2: " + l2);
failure = true;
}
}
if (filesNotEqual) {
System.out.println("Warning: replay files are not equal");
if (failure) {
throw new RuntimeException("Warning: replay files are not equal");
}
} catch (IOException ioe) {
throw new Error("Can't read replay files: " + ioe, ioe);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -30,7 +30,7 @@ import sun.hotspot.WhiteBox;
public class VMBase extends CiReplayBase {
public static void main(String args[]) {
new VMBase(args).runTest(/* needCoreDump = */ false, args);
new VMBase(args).runTest(/* needCoreDump = */ false);
}
public VMBase(String[] args) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -98,7 +98,7 @@ public class ClhsdbCDSCore {
}
try {
coreFileName = CoreUtils.getCoreFileLocation(crashOutput.getStdout());
coreFileName = CoreUtils.getCoreFileLocation(crashOutput.getStdout(), crashOutput.pid());
} catch (Exception e) {
cleanup();
throw e;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
@ -99,7 +99,7 @@ public class ClhsdbFindPC {
// Get the core file name if we are debugging a core instead of live process
if (withCore) {
coreFileName = CoreUtils.getCoreFileLocation(theApp.getOutput().getStdout());
coreFileName = CoreUtils.getCoreFileLocation(theApp.getOutput().getStdout(), theApp.getPid());
}
// Run 'jstack -v' command to get the findpc address

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
@ -65,7 +65,7 @@ public class ClhsdbPmap {
if (withCore) {
String crashOutput = theApp.getOutput().getStdout();
coreFileName = CoreUtils.getCoreFileLocation(crashOutput);
coreFileName = CoreUtils.getCoreFileLocation(crashOutput, theApp.getPid());
}
List<String> cmds = List.of("pmap");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 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
@ -65,7 +65,7 @@ public class ClhsdbPstack {
if (withCore) {
String crashOutput = theApp.getOutput().getStdout();
coreFileName = CoreUtils.getCoreFileLocation(crashOutput);
coreFileName = CoreUtils.getCoreFileLocation(crashOutput, theApp.getPid());
}
List<String> cmds = List.of("pstack -v");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -77,9 +77,9 @@ public class TestJmapCore {
// If we are going to force a core dump, apply "ulimit -c unlimited" if we can.
pb = CoreUtils.addCoreUlimitCommand(pb);
OutputAnalyzer output = ProcessTools.executeProcess(pb);
OutputAnalyzer output = ProcessTools.executeProcess(pb);
String coreFileName = CoreUtils.getCoreFileLocation(output.getStdout());
String coreFileName = CoreUtils.getCoreFileLocation(output.getStdout(), output.pid());
File core = new File(coreFileName);
File dumpFile = new File("heap.hprof");
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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
@ -566,6 +566,15 @@ public final class OutputAnalyzer {
return buffer.getExitValue();
}
/**
* Get the process' pid
*
* @return pid
*/
public long pid() {
return buffer.pid();
}
/**
* Get the contents of the output buffer (stdout and stderr) as list of strings.
* Output will be split by newlines.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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
@ -69,6 +69,13 @@ public interface OutputBuffer {
public String getStderr();
public int getExitValue();
/**
* Returns the pid if available
*
* @return pid
*/
public long pid();
public static OutputBuffer of(Process p, Charset cs) {
return new LazyOutputBuffer(p, cs);
}
@ -157,6 +164,11 @@ public interface OutputBuffer {
throw new OutputBufferException(e);
}
}
@Override
public long pid() {
return p.pid();
}
}
class EagerOutputBuffer implements OutputBuffer {
@ -184,5 +196,10 @@ public interface OutputBuffer {
public int getExitValue() {
return exitValue;
}
@Override
public long pid() {
throw new RuntimeException("no process");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 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
@ -101,7 +101,7 @@ public class CoreUtils {
* @param crashOutputString {@code String} to search in for the core file path
* @return Location of core file if found in the output, otherwise {@code null}.
*/
public static String getCoreFileLocation(String crashOutputString) throws IOException {
public static String getCoreFileLocation(String crashOutputString, long pid) throws IOException {
unzipCores(new File("."));
// Find the core file
@ -124,7 +124,8 @@ public class CoreUtils {
return coreFileLocation; // success!
}
// See if we can figure out the likely reason the core file was not found.
// See if we can figure out the likely reason the core file was not found. Recover from
// failure if possible.
// Throw SkippedException if appropriate.
if (Platform.isOSX()) {
File coresDir = new File("/cores");
@ -152,6 +153,30 @@ public class CoreUtils {
line = line.trim();
System.out.println(line);
if (line.startsWith("|")) {
if (line.split("\s", 2)[0].endsWith("systemd-coredump")) {
// A systemd linux system. Try to retrieve core
// file. It can take a few seconds for the system to
// process the just produced core file so we may need to
// retry a few times.
System.out.println("Running systemd-coredump: trying coredumpctl command");
String core = "core";
try {
for (int i = 0; i < 10; i++) {
Thread.sleep(5000);
OutputAnalyzer out = ProcessTools.executeProcess("coredumpctl", "dump", "-1", "-o", core, String.valueOf(pid));
if (!out.getOutput().contains("output may be incomplete")) {
break;
}
}
} catch(Throwable t) {
}
final File coreFile = new File(core);
if (coreFile.exists()) {
Asserts.assertGT(coreFile.length(), 0L, "Unexpected core size");
System.out.println("coredumpctl succeeded");
return core;
}
}
System.out.println(
"\nThis system uses a crash report tool ($cat /proc/sys/kernel/core_pattern).\n" +
"Core files might not be generated. Please reset /proc/sys/kernel/core_pattern\n" +