Created
June 11, 2023 09:45
-
-
Save Daomephsta/df5f331f915a089c7d5cf527af6ac894 to your computer and use it in GitHub Desktop.
Transaction debugging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.github.daomephsta; | |
import java.lang.StackWalker.StackFrame; | |
import java.util.List; | |
public interface OriginAware | |
{ | |
public List<StackFrame> silverfish_getOrigin(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.github.daomephsta.mixin; | |
import java.lang.StackWalker.StackFrame; | |
import java.util.Iterator; | |
import org.spongepowered.asm.mixin.Mixin; | |
import org.spongepowered.asm.mixin.Shadow; | |
import org.spongepowered.asm.mixin.injection.At; | |
import org.spongepowered.asm.mixin.injection.Inject; | |
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; | |
import io.github.daomephsta.OriginAware; | |
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; | |
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext; | |
import net.fabricmc.fabric.impl.transfer.transaction.TransactionManagerImpl; | |
@Mixin(TransactionManagerImpl.class) | |
public abstract class TransactionManagerImplMixin | |
{ | |
@Shadow | |
public abstract TransactionContext getCurrentUnsafe(); | |
@Inject(method = "openOuter", | |
at = @At(value = "NEW", target = "java.lang.IllegalStateException")) | |
private void silverfish_improveOuterTransactionError(CallbackInfoReturnable<Transaction> info) | |
{ | |
var originAware = (OriginAware) getCurrentUnsafe(); | |
var origin = new StringBuilder().append("Origin of current outer transaction\n"); | |
for (Iterator<StackFrame> iter = originAware.silverfish_getOrigin().iterator(); iter.hasNext();) | |
{ | |
StackFrame frame = iter.next(); | |
origin.append("\tat ").append(frame); | |
if (iter.hasNext()) origin.append('\n'); | |
} | |
System.err.println(origin); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.github.daomephsta.mixin; | |
import java.lang.StackWalker.Option; | |
import java.lang.StackWalker.StackFrame; | |
import java.util.List; | |
import java.util.stream.Stream; | |
import org.spongepowered.asm.mixin.Final; | |
import org.spongepowered.asm.mixin.Mixin; | |
import org.spongepowered.asm.mixin.Unique; | |
import org.spongepowered.asm.mixin.injection.At; | |
import org.spongepowered.asm.mixin.injection.Inject; | |
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | |
import io.github.daomephsta.OriginAware; | |
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; | |
@Mixin(targets = "net/fabricmc/fabric/impl/transfer/transaction/TransactionManagerImpl$TransactionImpl") | |
public abstract class TransactionOriginTracer implements Transaction, OriginAware | |
{ | |
@Unique | |
private @Final List<StackFrame> silverfish_origin; | |
@Inject(method = "<init>", at = @At("TAIL")) | |
private void silverfish_traceOrigin(CallbackInfo info) | |
{ | |
silverfish_origin = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE) | |
.walk(this::silverfish_originWalker); | |
} | |
private List<StackFrame> silverfish_originWalker(Stream<StackFrame> trace) | |
{ | |
return trace | |
// Trim the head until it's the frame calling the constructor | |
.dropWhile(this::silverfish_trimHead) | |
.toList(); | |
} | |
private boolean silverfish_trimHead(StackFrame frame) | |
{ | |
return frame.getMethodName().contains("silverfish_traceOrigin") || | |
frame.getMethodName().equals("<init>") && | |
// Check the constructor is declared by the target or a supertype | |
frame.getDeclaringClass().isAssignableFrom(getClass()); | |
} | |
@Override | |
public List<StackFrame> silverfish_getOrigin() | |
{ | |
return silverfish_origin; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment