mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-04 07:05:31 +00:00
8253442: bigapps SIGSEGV in DeadlockCycle::print_on_with
This commit is contained in:
parent
cc1238890c
commit
47e090a45a
@ -517,6 +517,7 @@ DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(ThreadsList * t_list,
|
||||
}
|
||||
previousThread = currentThread;
|
||||
waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor();
|
||||
waitingToLockRawMonitor = currentThread->current_pending_raw_monitor();
|
||||
if (concurrent_locks) {
|
||||
waitingToLockBlocker = currentThread->current_park_blocker();
|
||||
}
|
||||
@ -1050,7 +1051,8 @@ void DeadlockCycle::print_on_with(ThreadsList * t_list, outputStream* st) const
|
||||
waitingToLockMonitor->owner());
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
st->print_cr("%s \"%s\"", owner_desc, currentThread->name());
|
||||
} else if (waitingToLockBlocker != nullptr) {
|
||||
st->print(" waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)",
|
||||
p2i(waitingToLockBlocker),
|
||||
waitingToLockBlocker->klass()->external_name());
|
||||
@ -1059,8 +1061,10 @@ void DeadlockCycle::print_on_with(ThreadsList * t_list, outputStream* st) const
|
||||
oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker);
|
||||
currentThread = java_lang_Thread::thread(ownerObj);
|
||||
assert(currentThread != nullptr, "AbstractOwnableSynchronizer owning thread is unexpectedly null");
|
||||
st->print_cr("%s \"%s\"", owner_desc, currentThread->name());
|
||||
} else {
|
||||
assert(waitingToLockRawMonitor != nullptr, "some deadlock must have been found");
|
||||
}
|
||||
st->print_cr("%s \"%s\"", owner_desc, currentThread->name());
|
||||
}
|
||||
|
||||
st->cr();
|
||||
|
||||
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.
|
||||
*/
|
||||
|
||||
import org.testng.SkipException;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.Assert;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
import jdk.test.lib.dcmd.CommandExecutor;
|
||||
import jdk.test.lib.dcmd.JMXExecutor;
|
||||
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test of diagnostic command Thread.print with only JVMTI raw monitor.
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.compiler
|
||||
* java.management
|
||||
* jdk.internal.jvmstat/sun.jvmstat.monitor
|
||||
* @requires vm.jvmti
|
||||
* @run testng/othervm/native -agentlib:PrintRawMonitorLockTest PrintRawMonitorLockTest
|
||||
*/
|
||||
public class PrintRawMonitorLockTest {
|
||||
|
||||
static private void log(String s) { System.out.println(s); }
|
||||
static private String AGENT_LIB = "PrintRawMonitorLockTest";;
|
||||
|
||||
native static int createRawMonitors();
|
||||
native static int rawMonitorEnter(int id);
|
||||
|
||||
static {
|
||||
try {
|
||||
System.loadLibrary(AGENT_LIB);
|
||||
log("Loaded library: " + AGENT_LIB);
|
||||
} catch (UnsatisfiedLinkError ule) {
|
||||
log("Failed to load library: " + AGENT_LIB);
|
||||
log("java.library.path: " + System.getProperty("java.library.path"));
|
||||
throw ule;
|
||||
}
|
||||
}
|
||||
|
||||
CyclicBarrier readyBarrier = new CyclicBarrier(3);
|
||||
|
||||
private void waitForBarrier(CyclicBarrier b) {
|
||||
try {
|
||||
b.await();
|
||||
} catch (InterruptedException | BrokenBarrierException e) {
|
||||
Assert.fail("Test error: Caught unexpected exception:", e);
|
||||
}
|
||||
}
|
||||
|
||||
class RawMonitorThread extends Thread {
|
||||
int id;
|
||||
int otherid;
|
||||
|
||||
RawMonitorThread(int id, int otherid) {
|
||||
this.id = id;
|
||||
this.otherid = otherid;
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
int retCode = rawMonitorEnter(id);
|
||||
if (retCode != 0) {
|
||||
throw new RuntimeException("error in JVMTI RawMonitorEnter: " +
|
||||
"retCode=" + retCode);
|
||||
}
|
||||
log("entered lock1");
|
||||
|
||||
/* Hold lock on "lock" to show up in thread dump */
|
||||
/* Signal that we're ready for thread dump */
|
||||
waitForBarrier(readyBarrier);
|
||||
|
||||
retCode = rawMonitorEnter(otherid);
|
||||
if (retCode != 0) {
|
||||
throw new RuntimeException("error in JVMTI RawMonitorEnter: " +
|
||||
"retCode=" + retCode);
|
||||
}
|
||||
log("tried to enter lock2");
|
||||
}
|
||||
}
|
||||
|
||||
private void setupRawMonitors() {
|
||||
int retCode = createRawMonitors();
|
||||
if (retCode != 0) {
|
||||
throw new RuntimeException("error in JVMTI CreateRawMonitor: " +
|
||||
"retCode=" + retCode);
|
||||
}
|
||||
log("created threadLock");
|
||||
|
||||
}
|
||||
|
||||
public void run(CommandExecutor executor) {
|
||||
setupRawMonitors();
|
||||
|
||||
RawMonitorThread aThread = new RawMonitorThread(1, 2);
|
||||
aThread.start();
|
||||
|
||||
RawMonitorThread bThread = new RawMonitorThread(2, 1);
|
||||
bThread.start();
|
||||
|
||||
/* Wait for threads to get ready */
|
||||
waitForBarrier(readyBarrier);
|
||||
|
||||
OutputAnalyzer output;
|
||||
|
||||
while (true) {
|
||||
/* Execute */
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
output = executor.execute("Thread.print -l=true");
|
||||
if (output.getOutput().contains("Found 1 deadlock")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
output.shouldContain("waiting to lock JVM TI raw monitor");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jmx() {
|
||||
if (Thread.currentThread().isVirtual()) {
|
||||
throw new SkipException("skipping test since current thread is virtual thread");
|
||||
}
|
||||
run(new JMXExecutor());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "jvmti.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
static jvmtiEnv* jvmti = nullptr;
|
||||
static jrawMonitorID threadLock1 = nullptr;
|
||||
static char threadLockName1[] = "threadLock1";
|
||||
|
||||
static jrawMonitorID threadLock2 = nullptr;
|
||||
static char threadLockName2[] = "threadLock2";
|
||||
|
||||
#define LOG(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
printf("\n"); \
|
||||
fflush(stdout); \
|
||||
} while (0)
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_PrintRawMonitorLockTest_createRawMonitors(JNIEnv *jni, jclass cls) {
|
||||
if (jvmti->CreateRawMonitor(threadLockName1, &threadLock1) != JNI_OK) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
return jvmti->CreateRawMonitor(threadLockName2, &threadLock2);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_PrintRawMonitorLockTest_rawMonitorEnter(JNIEnv *jni, jclass cls, int id) {
|
||||
if (id == 1) {
|
||||
return jvmti->RawMonitorEnter(threadLock1);
|
||||
} else if (id == 2) {
|
||||
return jvmti->RawMonitorEnter(threadLock2);
|
||||
} else {
|
||||
return JNI_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/** Agent library initialization. */
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
|
||||
LOG("\nAgent_OnLoad started");
|
||||
|
||||
// create JVMTI environment
|
||||
if (jvm->GetEnv((void **) (&jvmti), JVMTI_VERSION) != JNI_OK) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// add specific capabilities for suspending thread
|
||||
jvmtiCapabilities suspendCaps;
|
||||
memset(&suspendCaps, 0, sizeof(suspendCaps));
|
||||
suspendCaps.can_suspend = 1;
|
||||
|
||||
jvmtiError err = jvmti->AddCapabilities(&suspendCaps);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
#endif
|
||||
LOG("Agent_OnLoad finished\n");
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user