mirror of
https://github.com/FabricMC/fabric.git
synced 2024-11-27 01:55:41 -05:00
Print the full stack trace from the dedicated server watchdog (#4052)
* Port FullSTackWatchdog * spotless * checkstyle * fixed package * added test mod * checkstyle
This commit is contained in:
parent
64afec5a95
commit
4854df7166
6 changed files with 211 additions and 0 deletions
|
@ -1 +1,5 @@
|
|||
version = getSubprojectVersion(project)
|
||||
|
||||
testDependencies(project, [
|
||||
':fabric-command-api-v2'
|
||||
])
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.impl.crash.report.info;
|
||||
|
||||
import java.lang.management.LockInfo;
|
||||
import java.lang.management.MonitorInfo;
|
||||
import java.lang.management.ThreadInfo;
|
||||
|
||||
public class ThreadPrinting {
|
||||
/**
|
||||
* A modified copy of {@link ThreadInfo#toString} without the MAX_FRAMES check.
|
||||
*/
|
||||
public static String fullThreadInfoToString(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,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.mixin.crash.report.info;
|
||||
|
||||
import java.lang.management.ThreadInfo;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
|
||||
import net.minecraft.server.dedicated.DedicatedServerWatchdog;
|
||||
|
||||
import net.fabricmc.fabric.impl.crash.report.info.ThreadPrinting;
|
||||
|
||||
@Mixin(DedicatedServerWatchdog.class)
|
||||
public class DedicatedServerWatchdogMixin {
|
||||
@ModifyArg(method = "createCrashReport(Ljava/lang/String;J)Lnet/minecraft/util/crash/CrashReport;",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "Ljava/lang/StringBuilder;append(Ljava/lang/Object;)Ljava/lang/StringBuilder;",
|
||||
ordinal = 0,
|
||||
remap = false)
|
||||
)
|
||||
private static Object printEntireThreadDump(Object object) {
|
||||
if (object instanceof ThreadInfo threadInfo) {
|
||||
return ThreadPrinting.fullThreadInfoToString(threadInfo);
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
"package": "net.fabricmc.fabric.mixin.crash.report.info",
|
||||
"compatibilityLevel": "JAVA_21",
|
||||
"mixins": [
|
||||
"DedicatedServerWatchdogMixin",
|
||||
"SystemDetailsMixin"
|
||||
],
|
||||
"injectors": {
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.test.crash.report.info;
|
||||
|
||||
import static net.minecraft.server.command.CommandManager.literal;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.dedicated.DedicatedServerWatchdog;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.crash.CrashReport;
|
||||
import net.minecraft.util.crash.ReportType;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||
|
||||
public class ThreadDumpTests implements ModInitializer {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadDumpTests.class);
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) ->
|
||||
dispatcher.register(literal("print_thread_dump_test_command").executes(this::executeDumpCommand)));
|
||||
}
|
||||
|
||||
private int executeDumpCommand(CommandContext<ServerCommandSource> context) {
|
||||
final ServerCommandSource source = context.getSource();
|
||||
CrashReport crashReport = DedicatedServerWatchdog.createCrashReport("Watching Server", context.getSource().getServer().getThread().threadId());
|
||||
LOGGER.info(crashReport.asString(ReportType.MINECRAFT_CRASH_REPORT));
|
||||
source.sendFeedback(() -> Text.literal("Thread Dump printed to console."), false);
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "fabric-crash-report-info-v1-testmod",
|
||||
"name": "Fabric Crash Report Info (v1) Test Mod",
|
||||
"version": "1.0.0",
|
||||
"environment": "*",
|
||||
"license": "Apache-2.0",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"net.fabricmc.fabric.test.crash.report.info.ThreadDumpTests"
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue