mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-17 01:24:33 +02:00
8290020: Deadlock in leakprofiler::emit_events during shutdown
Reviewed-by: mgronlun, dholmes, egahlin
This commit is contained in:
parent
7f0e9bd632
commit
e8568b890a
6 changed files with 30 additions and 34 deletions
|
@ -116,8 +116,8 @@ void Jfr::on_resolution(const Parse* parse, const ciKlass* holder, const ciMetho
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Jfr::on_vm_shutdown(bool exception_handler) {
|
void Jfr::on_vm_shutdown(bool exception_handler, bool halt) {
|
||||||
if (JfrRecorder::is_recording()) {
|
if (!halt && JfrRecorder::is_recording()) {
|
||||||
JfrEmergencyDump::on_vm_shutdown(exception_handler);
|
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_resolution(const GraphBuilder* builder, const ciKlass* holder, const ciMethod* target);
|
||||||
static void on_java_thread_start(JavaThread* starter, JavaThread* startee);
|
static void on_java_thread_start(JavaThread* starter, JavaThread* startee);
|
||||||
static void on_set_current_thread(JavaThread* jt, oop thread);
|
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 void on_vm_error_report(outputStream* st);
|
||||||
static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter);
|
static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter);
|
||||||
static bool on_start_flight_recording_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))
|
JVM_ENTRY_NO_ENV(void, JVM_Halt(jint code))
|
||||||
before_exit(thread);
|
before_exit(thread, true);
|
||||||
vm_exit(code);
|
vm_exit(code);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
|
@ -401,7 +401,7 @@ void print_statistics() {
|
||||||
// Note: before_exit() can be executed only once, if more than one threads
|
// 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
|
// are trying to shutdown the VM at the same time, only one thread
|
||||||
// can run before_exit() and all other threads must wait.
|
// 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_NOT_RUN 0
|
||||||
#define BEFORE_EXIT_RUNNING 1
|
#define BEFORE_EXIT_RUNNING 1
|
||||||
#define BEFORE_EXIT_DONE 2
|
#define BEFORE_EXIT_DONE 2
|
||||||
|
@ -448,7 +448,7 @@ void before_exit(JavaThread* thread) {
|
||||||
event.commit();
|
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
|
// Stop the WatcherThread. We do this before disenrolling various
|
||||||
// PeriodicTasks to reduce the likelihood of races.
|
// PeriodicTasks to reduce the likelihood of races.
|
||||||
|
|
|
@ -33,7 +33,7 @@ class JavaThread;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
|
|
||||||
// Execute code before all handles are released and thread is killed; prologue to vm_exit
|
// 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)
|
// Forced VM exit (i.e, internal error or JVM_Exit)
|
||||||
extern void vm_exit(int code);
|
extern void vm_exit(int code);
|
||||||
|
|
|
@ -76,41 +76,33 @@ public class TestDumpOnCrash {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
// Test without dumppath
|
// Test without dumppath
|
||||||
test(CrasherIllegalAccess.class, "", true);
|
test(CrasherIllegalAccess.class, "", true, null, true);
|
||||||
test(CrasherIllegalAccess.class, "", false);
|
test(CrasherIllegalAccess.class, "", false, null, true);
|
||||||
test(CrasherHalt.class, "", true);
|
|
||||||
test(CrasherHalt.class, "", false);
|
// 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
|
// Test with dumppath
|
||||||
Path dumppath = Files.createTempDirectory(null);
|
Path dumppath = Files.createTempDirectory(null);
|
||||||
try {
|
try {
|
||||||
test(CrasherIllegalAccess.class, "", true, dumppath.toString());
|
test(CrasherIllegalAccess.class, "", true, dumppath.toString(), true);
|
||||||
test(CrasherIllegalAccess.class, "", false, dumppath.toString());
|
test(CrasherIllegalAccess.class, "", false, dumppath.toString(), true);
|
||||||
test(CrasherHalt.class, "", true, dumppath.toString());
|
|
||||||
test(CrasherHalt.class, "", false, dumppath.toString());
|
|
||||||
} finally {
|
} finally {
|
||||||
dumppath.toFile().delete();
|
dumppath.toFile().delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test is excluded until 8219680 is fixed
|
// Test is excluded until 8219680 is fixed
|
||||||
// @ignore 8219680
|
// @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 {
|
private static void test(Class<?> crasher, String signal, boolean disk, String dumppath, boolean expectDump) 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 {
|
|
||||||
// The JVM may be in a state it can't recover from, so try three times
|
// The JVM may be in a state it can't recover from, so try three times
|
||||||
// before concluding functionality is not working.
|
// before concluding functionality is not working.
|
||||||
for (int attempt = 0; attempt < ATTEMPTS; attempt++) {
|
for (int attempt = 0; attempt < ATTEMPTS; attempt++) {
|
||||||
try {
|
try {
|
||||||
verify(runProcess(crasher, signal, disk, dumppath), expectedPath);
|
verify(runProcess(crasher, signal, disk, dumppath), dumppath, expectDump);
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("Attempt " + attempt + ". Verification failed:");
|
System.out.println("Attempt " + attempt + ". Verification failed:");
|
||||||
|
@ -148,19 +140,23 @@ public class TestDumpOnCrash {
|
||||||
return p.pid();
|
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";
|
String fileName = "hs_err_pid" + pid + ".jfr";
|
||||||
Path file = (dumppath == null) ? Paths.get(fileName) : Paths.get(dumppath, fileName);
|
Path file = (dumppath == null) ? Paths.get(fileName) : Paths.get(dumppath, fileName);
|
||||||
file = file.toAbsolutePath().normalize();
|
file = file.toAbsolutePath().normalize();
|
||||||
|
|
||||||
Asserts.assertTrue(Files.exists(file), "No emergency jfr recording file " + file + " exists");
|
if (expectDump) {
|
||||||
Asserts.assertNotEquals(Files.size(file), 0L, "File length 0. Should at least be some bytes");
|
Asserts.assertTrue(Files.exists(file), "No emergency jfr recording file " + file + " exists");
|
||||||
System.out.printf("File size=%d%n", Files.size(file));
|
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);
|
List<RecordedEvent> events = RecordingFile.readAllEvents(file);
|
||||||
Asserts.assertFalse(events.isEmpty(), "No event found");
|
Asserts.assertFalse(events.isEmpty(), "No event found");
|
||||||
System.out.printf("Found event %s%n", events.get(0).getEventType().getName());
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue