Skip to content

Commit

Permalink
Have Watchdog print the full stacktraces when doing a thread dump, fo…
Browse files Browse the repository at this point in the history
…r easier debugging (neoforged#512)
  • Loading branch information
TelepathicGrunt authored Jan 15, 2024
1 parent c1bf625 commit e24d6fe
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/dedicated/ServerWatchdog.java
+++ b/net/minecraft/server/dedicated/ServerWatchdog.java
@@ -48,7 +_,7 @@
@@ -48,14 +_,14 @@
ThreadMXBean threadmxbean = ManagementFactory.getThreadMXBean();
ThreadInfo[] athreadinfo = threadmxbean.dumpAllThreads(true, true);
StringBuilder stringbuilder = new StringBuilder();
Expand All @@ -9,3 +9,11 @@

for(ThreadInfo threadinfo : athreadinfo) {
if (threadinfo.getThreadId() == this.server.getRunningThread().getId()) {
error.setStackTrace(threadinfo.getStackTrace());
}

- stringbuilder.append(threadinfo);
+ stringbuilder.append(net.neoforged.neoforge.logging.ThreadInfoUtil.getEntireStacktrace(threadinfo));
stringbuilder.append("\n");
}

81 changes: 81 additions & 0 deletions src/main/java/net/neoforged/neoforge/logging/ThreadInfoUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (c) NeoForged and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/

package net.neoforged.neoforge.logging;

import java.lang.management.LockInfo;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;

public class ThreadInfoUtil {

public static String getEntireStacktrace(ThreadInfo threadInfo) {
StringBuilder sb = new StringBuilder("\"" + threadInfo.getThreadName() + "\"" +
(threadInfo.isDaemon() ? " daemon" : "") +
" prio=" + threadInfo.getPriority() +
" Id=" + threadInfo.getThreadId() + " " +
threadInfo.getThreadState());

if (threadInfo.getLockName() != null) {
sb.append(" on ").append(threadInfo.getLockName());
}

if (threadInfo.getLockOwnerName() != null) {
sb.append(" owned by \"").append(threadInfo.getLockOwnerName())
.append("\" Id=").append(threadInfo.getLockOwnerId());
}

if (threadInfo.isSuspended()) {
sb.append(" (suspended)");
}

if (threadInfo.isInNative()) {
sb.append(" (in native)");
}

sb.append('\n');

StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
for (int i = 0; i < stackTraceElements.length; i++) {
StackTraceElement ste = stackTraceElements[i];
sb.append("\tat ").append(ste.toString());
sb.append('\n');
if (i == 0 && threadInfo.getLockInfo() != null) {
Thread.State ts = threadInfo.getThreadState();
switch (ts) {
case BLOCKED -> {
sb.append("\t- blocked on ").append(threadInfo.getLockInfo());
sb.append('\n');
}
case WAITING, TIMED_WAITING -> {
sb.append("\t- waiting on ").append(threadInfo.getLockInfo());
sb.append('\n');
}
default -> {}
}
}

for (MonitorInfo mi : threadInfo.getLockedMonitors()) {
if (mi.getLockedStackDepth() == i) {
sb.append("\t- locked ").append(mi);
sb.append('\n');
}
}
}

LockInfo[] locks = threadInfo.getLockedSynchronizers();
if (locks.length > 0) {
sb.append("\n\tNumber of locked synchronizers = ").append(locks.length);
sb.append('\n');
for (LockInfo li : locks) {
sb.append("\t- ").append(li);
sb.append('\n');
}
}

sb.append('\n');
return sb.toString();
}
}

0 comments on commit e24d6fe

Please sign in to comment.