8267893: Improve jtreg test failure handler do get native/mixed stack traces for cores and live processes

Reviewed-by: iignatyev
This commit is contained in:
Leonid Mesnik 2021-06-10 17:45:53 +00:00
parent 1e1039a7c8
commit 8c8422e0f8
12 changed files with 152 additions and 29 deletions

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -38,7 +38,7 @@ SOURCES := ${SRC_DIR}/jdk/test/failurehandler/*.java \
CONF_DIR = src/share/conf CONF_DIR = src/share/conf
JAVA_RELEASE = 7 JAVA_RELEASE = 15
TARGET_JAR = ${IMAGE_DIR}/lib/jtregFailureHandler.jar TARGET_JAR = ${IMAGE_DIR}/lib/jtregFailureHandler.jar
@ -116,4 +116,3 @@ build: classes native
.PHONY: all build classes native test require_env clean .PHONY: all build classes native test require_env clean
.DEFAULT: all .DEFAULT: all

View File

@ -1,4 +1,4 @@
Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,7 @@ The library uses JTHarness Observer and jtreg TimeoutHandler extensions points.
DEPENDENCES DEPENDENCES
The library requires jtreg 4b13+ and JDK 7+. The library requires jtreg 4b13+ and JDK 15+.
BUILDING BUILDING
@ -102,4 +102,3 @@ $ ${JTREG_HOME}/bin/jtreg -jdk:${JAVA_HOME} \
-timeoutHandler:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler\ -timeoutHandler:jdk.test.failurehandler.jtreg.GatherProcessInfoTimeoutHandler\
-observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver \ -observer:jdk.test.failurehandler.jtreg.GatherDiagnosticInfoObserver \
${WS}/hotspot/test/ ${WS}/hotspot/test/

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.failurehandler;
import java.nio.file.Path;
public interface CoreInfoGatherer {
void gatherCoreInfo(HtmlSection section, Path core);
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -51,6 +51,10 @@ public final class GathererFactory {
return create(); return create();
} }
public CoreInfoGatherer getCoreInfoGatherer() {
return create();
}
private ToolKit create() { private ToolKit create() {
Properties osProperty = Utils.getProperties(osName); Properties osProperty = Utils.getProperties(osName);
try { try {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,19 +26,25 @@ package jdk.test.failurehandler;
import jdk.test.failurehandler.action.ActionSet; import jdk.test.failurehandler.action.ActionSet;
import jdk.test.failurehandler.action.ActionHelper; import jdk.test.failurehandler.action.ActionHelper;
import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.Deque; import java.util.Deque;
import java.util.zip.GZIPInputStream;
public class ToolKit implements EnvironmentInfoGatherer, ProcessInfoGatherer { public class ToolKit implements EnvironmentInfoGatherer, ProcessInfoGatherer, CoreInfoGatherer {
private final List<ActionSet> actions = new ArrayList<>(); private final List<ActionSet> actions = new ArrayList<>();
private final ActionHelper helper; private final ActionHelper helper;
private final PrintWriter log;
public ToolKit(ActionHelper helper, PrintWriter log, String... names) { public ToolKit(ActionHelper helper, PrintWriter log, String... names) {
this.helper = helper; this.helper = helper;
this.log = log;
for (String name : names) { for (String name : names) {
actions.add(new ActionSet(helper, log, name)); actions.add(new ActionSet(helper, log, name));
} }
@ -51,6 +57,27 @@ public class ToolKit implements EnvironmentInfoGatherer, ProcessInfoGatherer {
} }
} }
@Override
public void gatherCoreInfo(HtmlSection section, Path core) {
if (core.getFileName().toString().endsWith(".gz")) {
Path unpackedCore = Path.of(core.toString().replace(".gz", ""));
try (GZIPInputStream gzis = new GZIPInputStream(Files.newInputStream(core))) {
Files.copy(gzis, unpackedCore);
for (ActionSet set : actions) {
set.gatherCoreInfo(section, unpackedCore);
}
Files.delete(unpackedCore);
} catch (IOException ioe) {
log.printf("Unexpected exception whilc opening %s", core.getFileName().toString());
ioe.printStackTrace(log);
}
} else {
for (ActionSet set : actions) {
set.gatherCoreInfo(section, core);
}
}
}
@Override @Override
public void gatherProcessInfo(HtmlSection section, long pid) { public void gatherProcessInfo(HtmlSection section, long pid) {
// as some of actions can kill a process, we need to get children of all // as some of actions can kill a process, we need to get children of all

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,8 +23,6 @@
package jdk.test.failurehandler.action; package jdk.test.failurehandler.action;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import jdk.test.failurehandler.value.InvalidValueException; import jdk.test.failurehandler.value.InvalidValueException;
import jdk.test.failurehandler.value.Value; import jdk.test.failurehandler.value.Value;
import jdk.test.failurehandler.value.ValueHandler; import jdk.test.failurehandler.value.ValueHandler;
@ -134,7 +132,7 @@ public class ActionHelper {
.directory(workDir.toFile()); .directory(workDir.toFile());
} }
private File findApp(String app) { public File findApp(String app) {
String name = app + executableSuffix; String name = app + executableSuffix;
for (Path pathElem : paths) { for (Path pathElem : paths) {
File result = pathElem.resolve(name).toFile(); File result = pathElem.resolve(name).toFile();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,19 +23,26 @@
package jdk.test.failurehandler.action; package jdk.test.failurehandler.action;
import jdk.test.failurehandler.CoreInfoGatherer;
import jdk.test.failurehandler.ProcessInfoGatherer; import jdk.test.failurehandler.ProcessInfoGatherer;
import jdk.test.failurehandler.EnvironmentInfoGatherer; import jdk.test.failurehandler.EnvironmentInfoGatherer;
import jdk.test.failurehandler.HtmlSection; import jdk.test.failurehandler.HtmlSection;
import jdk.test.failurehandler.Utils; import jdk.test.failurehandler.Utils;
import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.zip.GZIPInputStream;
public class ActionSet implements ProcessInfoGatherer, EnvironmentInfoGatherer { public class ActionSet implements ProcessInfoGatherer, EnvironmentInfoGatherer, CoreInfoGatherer {
private static final String ENVIRONMENT_PROPERTY = "environment"; private static final String ENVIRONMENT_PROPERTY = "environment";
private static final String ON_PID_PROPERTY = "onTimeout"; private static final String ON_PID_PROPERTY = "onTimeout";
private static final String CORES_PROPERTY = "cores";
private final ActionHelper helper; private final ActionHelper helper;
@ -46,6 +53,7 @@ public class ActionSet implements ProcessInfoGatherer, EnvironmentInfoGatherer {
private final String name; private final String name;
private final List<SimpleAction> environmentActions; private final List<SimpleAction> environmentActions;
private final List<PatternAction> processActions; private final List<PatternAction> processActions;
private final List<PatternAction> coreActions;
public ActionSet(ActionHelper helper, PrintWriter log, String name) { public ActionSet(ActionHelper helper, PrintWriter log, String name) {
@ -55,6 +63,7 @@ public class ActionSet implements ProcessInfoGatherer, EnvironmentInfoGatherer {
Properties p = Utils.getProperties(name); Properties p = Utils.getProperties(name);
environmentActions = getSimpleActions(log, p, ENVIRONMENT_PROPERTY); environmentActions = getSimpleActions(log, p, ENVIRONMENT_PROPERTY);
processActions = getPatternActions(log, p, ON_PID_PROPERTY); processActions = getPatternActions(log, p, ON_PID_PROPERTY);
coreActions = getPatternActions(log, p, CORES_PROPERTY);
} }
private List<SimpleAction> getSimpleActions(PrintWriter log, Properties p, private List<SimpleAction> getSimpleActions(PrintWriter log, Properties p,
@ -123,4 +132,11 @@ public class ActionSet implements ProcessInfoGatherer, EnvironmentInfoGatherer {
helper.runPatternAction(action, section); helper.runPatternAction(action, section);
} }
} }
@Override
public void gatherCoreInfo(HtmlSection section, Path core) {
for (PatternAction action : coreActions) {
helper.runPatternAction(action, section, core.toString());
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -59,6 +59,9 @@ public class PatternAction implements Action {
for (int i = 0, n = args.length; i < n; ++i) { for (int i = 0, n = args.length; i < n; ++i) {
args[i] = args[i].replace(pattern, value) ; args[i] = args[i].replace(pattern, value) ;
} }
for (int i = 0, n = args.length; i < n; ++i) {
args[i] = args[i].replace("%java", helper.findApp("java").getAbsolutePath());
}
return action.prepareProcess(section.getWriter(), helper); return action.prepareProcess(section.getWriter(), helper);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -33,10 +33,9 @@ import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
/** /**
* The jtreg test execution observer, which gathers info about * The jtreg test execution observer, which gathers info about
@ -45,6 +44,8 @@ import java.util.Map;
public class GatherDiagnosticInfoObserver implements Harness.Observer { public class GatherDiagnosticInfoObserver implements Harness.Observer {
public static final String LOG_FILENAME = "environment.log"; public static final String LOG_FILENAME = "environment.log";
public static final String ENVIRONMENT_OUTPUT = "environment.html"; public static final String ENVIRONMENT_OUTPUT = "environment.html";
public static final String CORES_OUTPUT = "cores.html";
private Path compileJdk; private Path compileJdk;
private Path testJdk; private Path testJdk;
@ -64,18 +65,19 @@ public class GatherDiagnosticInfoObserver implements Harness.Observer {
workDir.toFile().mkdir(); workDir.toFile().mkdir();
String name = getClass().getName(); String name = getClass().getName();
PrintWriter log; PrintWriter log1;
boolean needClose = false; boolean needClose = false;
try { try {
log = new PrintWriter(new FileWriter( log1 = new PrintWriter(new FileWriter(
workDir.resolve(LOG_FILENAME).toFile(), true), true); workDir.resolve(LOG_FILENAME).toFile(), true), true);
needClose = true; needClose = true;
} catch (IOException e) { } catch (IOException e) {
log = new PrintWriter(System.out); log1 = new PrintWriter(System.out);
log.printf("ERROR: %s cannot open log file %s", name, log1.printf("ERROR: %s cannot open log file %s", name,
LOG_FILENAME); LOG_FILENAME);
e.printStackTrace(log); e.printStackTrace(log1);
} }
final PrintWriter log = log1;
try { try {
log.printf("%s ---%n", name); log.printf("%s ---%n", name);
GathererFactory gathererFactory = new GathererFactory( GathererFactory gathererFactory = new GathererFactory(
@ -83,6 +85,11 @@ public class GatherDiagnosticInfoObserver implements Harness.Observer {
testJdk, compileJdk); testJdk, compileJdk);
gatherEnvInfo(workDir, name, log, gatherEnvInfo(workDir, name, log,
gathererFactory.getEnvironmentInfoGatherer()); gathererFactory.getEnvironmentInfoGatherer());
Files.walk(workDir)
.filter(Files::isRegularFile)
.filter(f -> (f.getFileName().toString().contains("core") || f.getFileName().toString().contains("mdmp")))
.forEach(core -> gatherCoreInfo(workDir, name,
core, log, gathererFactory.getCoreInfoGatherer()));
} catch (Throwable e) { } catch (Throwable e) {
log.printf("ERROR: exception in observer %s:", name); log.printf("ERROR: exception in observer %s:", name);
e.printStackTrace(log); e.printStackTrace(log);
@ -96,6 +103,22 @@ public class GatherDiagnosticInfoObserver implements Harness.Observer {
} }
} }
private void gatherCoreInfo(Path workDir, String name, Path core, PrintWriter log,
CoreInfoGatherer gatherer) {
File output = workDir.resolve(CORES_OUTPUT).toFile();
try (HtmlPage html = new HtmlPage(new PrintWriter(
new FileWriter(output, true), true))) {
try (ElapsedTimePrinter timePrinter
= new ElapsedTimePrinter(new Stopwatch(), name, log)) {
gatherer.gatherCoreInfo(html.getRootSection(), core);
}
} catch (Throwable e) {
log.printf("ERROR: exception in observer on getting environment "
+ "information %s:", name);
e.printStackTrace(log);
}
}
private void gatherEnvInfo(Path workDir, String name, PrintWriter log, private void gatherEnvInfo(Path workDir, String name, PrintWriter log,
EnvironmentInfoGatherer gatherer) { EnvironmentInfoGatherer gatherer) {
File output = workDir.resolve(ENVIRONMENT_OUTPUT).toFile(); File output = workDir.resolve(ENVIRONMENT_OUTPUT).toFile();

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,7 @@ onTimeout=\
jcmd.vm.symboltable jcmd.vm.uptime jcmd.vm.dynlibs \ jcmd.vm.symboltable jcmd.vm.uptime jcmd.vm.dynlibs \
jcmd.vm.system_properties \ jcmd.vm.system_properties \
jcmd.gc.heap_info jcmd.gc.class_histogram jcmd.gc.finalizer_info \ jcmd.gc.heap_info jcmd.gc.class_histogram jcmd.gc.finalizer_info \
jstack jstack jhsdb.jstack
jinfo.app=jinfo jinfo.app=jinfo
@ -51,6 +51,7 @@ jcmd.vm.symboltable.args=%p VM.symboltable
jcmd.vm.uptime.args=%p VM.uptime jcmd.vm.uptime.args=%p VM.uptime
jcmd.vm.dynlibs.args=%p VM.dynlibs jcmd.vm.dynlibs.args=%p VM.dynlibs
jcmd.vm.system_properties.args=%p VM.system_properties jcmd.vm.system_properties.args=%p VM.system_properties
jcmd.vm.info.args=%p VM.info
jcmd.gc.class_histogram.args=%p GC.class_histogram jcmd.gc.class_histogram.args=%p GC.class_histogram
jcmd.gc.finalizer_info.args=%p GC.finalizer_info jcmd.gc.finalizer_info.args=%p GC.finalizer_info
@ -60,6 +61,15 @@ jstack.app=jstack
jstack.args=-e -l %p jstack.args=-e -l %p
jstack.params.repeat=6 jstack.params.repeat=6
jhsdb.app=jhsdb
jhsdb.jstack.args=jstack --mixed --pid %p
jhsdb.jstack.params.repeat=6
cores=jhsdb.jstack
jhsdb.jstack.app=jhsdb
# Assume that java standard laucher has been used
jhsdb.jstack.args=jstack --mixed --core %p --exe %java
################################################################################ ################################################################################
# environment info to gather # environment info to gather
################################################################################ ################################################################################

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -32,6 +32,7 @@ onTimeout=\
native.pmap.normal native.pmap.everything \ native.pmap.normal native.pmap.everything \
native.files native.locks \ native.files native.locks \
native.stack native.core native.stack native.core
################################################################################ ################################################################################
native.pattern=%p native.pattern=%p
native.javaOnly=false native.javaOnly=false
@ -55,6 +56,13 @@ native.stack.params.repeat=6
# has to be the last command # has to be the last command
native.core.app=kill native.core.app=kill
native.core.args=-ABRT %p native.core.args=-ABRT %p
cores=native.gdb
native.gdb.app=gdb
# Assume that java standard laucher has been used
native.gdb.args=%java\0-c\0%p\0-batch\0-ex\0thread apply all backtrace
native.gdb.args.delimiter=\0
################################################################################ ################################################################################
# environment info to gather # environment info to gather
################################################################################ ################################################################################
@ -123,4 +131,3 @@ screenshot.args=-c\0\
' | jshell - ' | jshell -
screenshot.args.delimiter=\0 screenshot.args.delimiter=\0
################################################################################ ################################################################################

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -64,6 +64,13 @@ native.stack.args=-c\0DevToolsSecurity --status | grep -q enabled && lldb -o 'at
# has to be the last command # has to be the last command
native.core.app=kill native.core.app=kill
native.core.args=-ABRT %p native.core.args=-ABRT %p
cores=native.lldb
native.lldb.app=lldb
native.lldb.delimiter=\0
# Assume that java standard laucher has been used
native.lldb.args=--core\0%p\0%java\0-o\0thread backtrace all\0-o\0quit
################################################################################ ################################################################################
# environment info to gather # environment info to gather
################################################################################ ################################################################################