Skip to content

Commit 575d6f0

Browse files
committed
include recovered mixin failures in crash reports to make debugging future crashes due to it easier
1 parent da31478 commit 575d6f0

10 files changed

Lines changed: 93 additions & 23 deletions

File tree

src/client/java/dev/isxander/debugify/client/gui/ConfigGuiHelper.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package dev.isxander.debugify.client.gui;
22

3-
import dev.isxander.debugify.client.DebugifyClient;
43
import dev.isxander.debugify.config.DebugifyConfig;
54
import dev.isxander.debugify.fixes.BugFix;
65
import dev.isxander.debugify.fixes.FixCategory;
7-
import dev.isxander.debugify.mixinplugin.DebugifyErrorHandler;
6+
import dev.isxander.debugify.error.DebugifyErrorHandler;
87
import dev.isxander.yacl3.api.*;
98
import dev.isxander.yacl3.api.controller.BooleanControllerBuilder;
109
import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder;

src/main/java/dev/isxander/debugify/Debugify.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import dev.isxander.debugify.config.DebugifyConfig;
44
import dev.isxander.debugify.fixes.BugFix;
5-
import dev.isxander.debugify.mixinplugin.DebugifyErrorHandler;
5+
import dev.isxander.debugify.error.DebugifyErrorHandler;
66
import net.fabricmc.api.EnvType;
77
import net.fabricmc.loader.api.FabricLoader;
88
import net.fabricmc.loader.api.Version;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package dev.isxander.debugify.error;
2+
3+
import java.io.PrintWriter;
4+
import java.io.StringWriter;
5+
import java.util.Set;
6+
7+
/**
8+
* Adds details to crash report if Debugify recovered from a mixin application error.
9+
* This is needed because in some cases, partial mixin application may lead to runtime crashes,
10+
* and crash reports will not include the original mixin application error details that Debugify
11+
* logs in {@link DebugifyErrorHandler}.
12+
*/
13+
public class CrashReportInjector {
14+
public static void addDetailsToCrashReport(StringBuilder sb) {
15+
Set<MixinErrorEntry> erroredFixes = DebugifyErrorHandler.getErroredFixes();
16+
if (!erroredFixes.isEmpty()) {
17+
sb.append("\n-- Debugify recovered from mixin application errors --\n");
18+
sb.append("Some bug fixes failed to apply, which could have led to this crash.\n");
19+
sb.append("This log does not mean Debugify caused the crash, but it could have.\n\n");
20+
for (var entry : erroredFixes) {
21+
sb.append(stringifyErrorEntry(entry)).append("\n");
22+
}
23+
}
24+
}
25+
26+
private static String stringifyErrorEntry(MixinErrorEntry entry) {
27+
var stringWriter = new StringWriter();
28+
var printWriter = new PrintWriter(stringWriter);
29+
entry.throwable().printStackTrace(printWriter);
30+
String stacktrace = stringWriter.toString();
31+
32+
return "%s fix failed to fully apply due to %s during %s\n%s".formatted(
33+
entry.fix().bugId(),
34+
entry.mixinInfo().getName(),
35+
entry.errorStage().name(),
36+
stacktrace
37+
);
38+
}
39+
}

src/main/java/dev/isxander/debugify/mixinplugin/DebugifyErrorHandler.java renamed to src/main/java/dev/isxander/debugify/error/DebugifyErrorHandler.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,49 @@
1-
package dev.isxander.debugify.mixinplugin;
1+
package dev.isxander.debugify.error;
22

33
import dev.isxander.debugify.Debugify;
44
import dev.isxander.debugify.fixes.BugFixData;
5-
import org.objectweb.asm.tree.ClassNode;
5+
import dev.isxander.debugify.mixinplugin.BugFixDataCache;
66
import org.spongepowered.asm.mixin.extensibility.IMixinConfig;
77
import org.spongepowered.asm.mixin.extensibility.IMixinErrorHandler;
88
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
9-
import org.spongepowered.asm.service.MixinService;
109

11-
import java.io.IOException;
10+
import java.util.Collections;
1211
import java.util.HashSet;
1312
import java.util.Optional;
1413
import java.util.Set;
1514

1615
public class DebugifyErrorHandler implements IMixinErrorHandler {
17-
private static final Set<BugFixData> ERRORED_FIXES = new HashSet<>();
16+
private static final Set<MixinErrorEntry> ERRORED_FIXES = new HashSet<>();
1817

1918
@Override
2019
public ErrorAction onPrepareError(IMixinConfig config, Throwable th, IMixinInfo mixin, ErrorAction action) {
21-
return handleError(action, mixin);
20+
return handleError(action, mixin, th, ErrorStage.PREPARE);
2221
}
2322

2423
@Override
2524
public ErrorAction onApplyError(String targetClassName, Throwable th, IMixinInfo mixin, ErrorAction action) {
26-
return handleError(action, mixin);
25+
return handleError(action, mixin, th, ErrorStage.APPLY);
2726
}
2827

29-
private ErrorAction handleError(ErrorAction usualAction, IMixinInfo mixin) {
28+
private ErrorAction handleError(ErrorAction usualAction, IMixinInfo mixin, Throwable th, ErrorStage stage) {
3029
Optional<BugFixData> bugFix = BugFixDataCache.getIfResolved(mixin.getClassName());
3130
if (bugFix.isEmpty())
3231
return usualAction;
3332

3433
BugFixData fix = bugFix.get();
35-
ERRORED_FIXES.add(fix);
34+
ERRORED_FIXES.add(new MixinErrorEntry(fix, mixin, th, stage));
3635

3736
// no need to add exception here, it's already logged under ErrorAction.WARN
3837
Debugify.LOGGER.error("Failed to fully apply bug fix {}, mixin class {} will not be applied! This may cause runtime errors if a partial injection occurs.", fix.bugId(), mixin.getName());
3938
return ErrorAction.WARN;
4039
}
4140

4241
public static boolean hasErrored(BugFixData fix) {
43-
return ERRORED_FIXES.contains(fix);
42+
return ERRORED_FIXES.stream().anyMatch(entry -> entry.fix().equals(fix));
4443
}
44+
45+
public static Set<MixinErrorEntry> getErroredFixes() {
46+
return Collections.unmodifiableSet(ERRORED_FIXES);
47+
}
48+
4549
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package dev.isxander.debugify.error;
2+
3+
public enum ErrorStage {
4+
PREPARE,
5+
APPLY
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package dev.isxander.debugify.error;
2+
3+
import dev.isxander.debugify.fixes.BugFixData;
4+
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
5+
6+
public record MixinErrorEntry(BugFixData fix, IMixinInfo mixinInfo, Throwable throwable, ErrorStage errorStage) {
7+
}

src/main/java/dev/isxander/debugify/mixinplugin/BugFixDataCache.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919
public class BugFixDataCache {
2020
private static final Map<String, ResolvedBugFixData> bugFixDataByMixinClass = new HashMap<>();
2121

22-
static Optional<BugFixData> getOrResolve(String mixinClassName) {
22+
public static Optional<BugFixData> getOrResolve(String mixinClassName) {
2323
return Optional.ofNullable(
2424
bugFixDataByMixinClass.computeIfAbsent(mixinClassName, BugFixDataCache::resolve)
2525
.data()
2626
);
2727
}
2828

29-
static Optional<BugFixData> getIfResolved(String mixinClassName) {
29+
public static Optional<BugFixData> getIfResolved(String mixinClassName) {
3030
return Optional.ofNullable(bugFixDataByMixinClass.get(mixinClassName))
3131
.flatMap(resolved -> Optional.ofNullable(resolved.data()));
3232
}

src/main/java/dev/isxander/debugify/mixinplugin/MixinPlugin.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,13 @@
22

33
import dev.isxander.debugify.Debugify;
44
import dev.isxander.debugify.api.DebugifyApi;
5-
import dev.isxander.debugify.fixes.BugFix;
6-
import dev.isxander.debugify.fixes.FixCategory;
5+
import dev.isxander.debugify.error.DebugifyErrorHandler;
76
import dev.isxander.debugify.fixes.BugFixData;
8-
import dev.isxander.debugify.fixes.OS;
97
import net.fabricmc.loader.api.FabricLoader;
10-
import org.jetbrains.annotations.Nullable;
11-
import org.objectweb.asm.tree.AnnotationNode;
128
import org.objectweb.asm.tree.ClassNode;
139
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
1410
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
15-
import org.spongepowered.asm.service.MixinService;
16-
import org.spongepowered.asm.util.Annotations;
1711

18-
import java.io.IOException;
1912
import java.util.*;
2013

2114
public class MixinPlugin implements IMixinConfigPlugin {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package dev.isxander.debugify.mixins.errorhandler;
2+
3+
import com.llamalad7.mixinextras.expression.Definition;
4+
import com.llamalad7.mixinextras.expression.Expression;
5+
import dev.isxander.debugify.error.CrashReportInjector;
6+
import net.minecraft.CrashReport;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
11+
12+
@Mixin(CrashReport.class)
13+
public class CrashReportMixin {
14+
@Definition(id = "systemReport", field = "Lnet/minecraft/CrashReport;systemReport:Lnet/minecraft/SystemReport;")
15+
@Definition(id = "appendToCrashReportString", method = "Lnet/minecraft/SystemReport;appendToCrashReportString(Ljava/lang/StringBuilder;)V")
16+
@Expression("this.systemReport.appendToCrashReportString(?)")
17+
@Inject(method = "getDetails(Ljava/lang/StringBuilder;)V", at = @At("MIXINEXTRAS:EXPRESSION"))
18+
private void appendCrashReport(StringBuilder sb, CallbackInfo ci) {
19+
CrashReportInjector.addDetailsToCrashReport(sb);
20+
}
21+
}

src/main/resources/debugify.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"basic.mc89146.ChunkAccessMixin",
7474
"basic.mc93018.AnimalMixin",
7575
"basic.mc94054.WallClimberNavigationMixin",
76+
"errorhandler.CrashReportMixin",
7677
"gameplay.mc8187.MixinTreeFeature"
7778
]
7879
}

0 commit comments

Comments
 (0)