8290020: Deadlock in leakprofiler::emit_events during shutdown

Reviewed-by: mgronlun, dholmes, egahlin
This commit is contained in:
Ludvig Janiuk 2022-07-12 15:54:36 +00:00 committed by Erik Gahlin
parent 7f0e9bd632
commit e8568b890a
6 changed files with 30 additions and 34 deletions
src/hotspot/share
test/jdk/jdk/jfr/jvm

@ -116,8 +116,8 @@ void Jfr::on_resolution(const Parse* parse, const ciKlass* holder, const ciMetho
}
#endif
void Jfr::on_vm_shutdown(bool exception_handler) {
if (JfrRecorder::is_recording()) {
void Jfr::on_vm_shutdown(bool exception_handler, bool halt) {
if (!halt && JfrRecorder::is_recording()) {
JfrEmergencyDump::on_vm_shutdown(exception_handler);
}
}

@ -65,7 +65,7 @@ class Jfr : AllStatic {
static void on_resolution(const GraphBuilder* builder, const ciKlass* holder, const ciMethod* target);
static void on_java_thread_start(JavaThread* starter, JavaThread* startee);
static void on_set_current_thread(JavaThread* jt, oop thread);
static void on_vm_shutdown(bool exception_handler = false);
static void on_vm_shutdown(bool exception_handler = false, bool halt = false);
static void on_vm_error_report(outputStream* st);
static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter);
static bool on_start_flight_recording_option(const JavaVMOption** option, char* delimiter);

@ -441,7 +441,7 @@ JVM_END
JVM_ENTRY_NO_ENV(void, JVM_Halt(jint code))
before_exit(thread);
before_exit(thread, true);
vm_exit(code);
JVM_END

@ -401,7 +401,7 @@ void print_statistics() {
// Note: before_exit() can be executed only once, if more than one threads
// are trying to shutdown the VM at the same time, only one thread
// can run before_exit() and all other threads must wait.
void before_exit(JavaThread* thread) {
void before_exit(JavaThread* thread, bool halt) {
#define BEFORE_EXIT_NOT_RUN 0
#define BEFORE_EXIT_RUNNING 1
#define BEFORE_EXIT_DONE 2
@ -448,7 +448,7 @@ void before_exit(JavaThread* thread) {
event.commit();
}
JFR_ONLY(Jfr::on_vm_shutdown();)
JFR_ONLY(Jfr::on_vm_shutdown(false, halt);)
// Stop the WatcherThread. We do this before disenrolling various
// PeriodicTasks to reduce the likelihood of races.

@ -33,7 +33,7 @@ class JavaThread;
class Symbol;
// Execute code before all handles are released and thread is killed; prologue to vm_exit
extern void before_exit(JavaThread * thread);
extern void before_exit(JavaThread * thread, bool halt = false);
// Forced VM exit (i.e, internal error or JVM_Exit)
extern void vm_exit(int code);

@ -76,41 +76,33 @@ public class TestDumpOnCrash {
public static void main(String[] args) throws Exception {
// Test without dumppath
test(CrasherIllegalAccess.class, "", true);
test(CrasherIllegalAccess.class, "", false);
test(CrasherHalt.class, "", true);
test(CrasherHalt.class, "", false);
test(CrasherIllegalAccess.class, "", true, null, true);
test(CrasherIllegalAccess.class, "", false, null, true);
// JDK-8290020 disables dumps when calling halt, so expect no dump.
test(CrasherHalt.class, "", true, null, false);
test(CrasherHalt.class, "", false, null, false);
// Test with dumppath
Path dumppath = Files.createTempDirectory(null);
try {
test(CrasherIllegalAccess.class, "", true, dumppath.toString());
test(CrasherIllegalAccess.class, "", false, dumppath.toString());
test(CrasherHalt.class, "", true, dumppath.toString());
test(CrasherHalt.class, "", false, dumppath.toString());
test(CrasherIllegalAccess.class, "", true, dumppath.toString(), true);
test(CrasherIllegalAccess.class, "", false, dumppath.toString(), true);
} finally {
dumppath.toFile().delete();
}
// Test is excluded until 8219680 is fixed
// @ignore 8219680
// test(CrasherSig.class, "FPE", true);
// test(CrasherSig.class, "FPE", true, true);
}
private static void test(Class<?> crasher, String signal, boolean disk) throws Exception {
test(crasher, signal, disk, null);
}
private static void test(Class<?> crasher, String signal, boolean disk, String dumppath) throws Exception {
test(crasher, signal, disk, dumppath, dumppath);
}
private static void test(Class<?> crasher, String signal, boolean disk, String dumppath, String expectedPath) throws Exception {
private static void test(Class<?> crasher, String signal, boolean disk, String dumppath, boolean expectDump) throws Exception {
// The JVM may be in a state it can't recover from, so try three times
// before concluding functionality is not working.
for (int attempt = 0; attempt < ATTEMPTS; attempt++) {
try {
verify(runProcess(crasher, signal, disk, dumppath), expectedPath);
verify(runProcess(crasher, signal, disk, dumppath), dumppath, expectDump);
return;
} catch (Exception e) {
System.out.println("Attempt " + attempt + ". Verification failed:");
@ -148,19 +140,23 @@ public class TestDumpOnCrash {
return p.pid();
}
private static void verify(long pid, String dumppath) throws IOException {
private static void verify(long pid, String dumppath, boolean expectDump) throws IOException {
String fileName = "hs_err_pid" + pid + ".jfr";
Path file = (dumppath == null) ? Paths.get(fileName) : Paths.get(dumppath, fileName);
file = file.toAbsolutePath().normalize();
Asserts.assertTrue(Files.exists(file), "No emergency jfr recording file " + file + " exists");
Asserts.assertNotEquals(Files.size(file), 0L, "File length 0. Should at least be some bytes");
System.out.printf("File size=%d%n", Files.size(file));
if (expectDump) {
Asserts.assertTrue(Files.exists(file), "No emergency jfr recording file " + file + " exists");
Asserts.assertNotEquals(Files.size(file), 0L, "File length 0. Should at least be some bytes");
System.out.printf("File size=%d%n", Files.size(file));
List<RecordedEvent> events = RecordingFile.readAllEvents(file);
Asserts.assertFalse(events.isEmpty(), "No event found");
System.out.printf("Found event %s%n", events.get(0).getEventType().getName());
List<RecordedEvent> events = RecordingFile.readAllEvents(file);
Asserts.assertFalse(events.isEmpty(), "No event found");
System.out.printf("Found event %s%n", events.get(0).getEventType().getName());
Files.delete(file);
Files.delete(file);
} else {
Asserts.assertFalse(Files.exists(file), "Emergency jfr recording file " + file + " exists but wasn't expected");
}
}
}