mcghidra/src/main/java/eu/starsong/ghidra/util/TransactionHelper.java
Teal Bauer 3222cf9866
Some checks failed
Build Ghidra Plugin / build (push) Has been cancelled
feat: upgrade to Ghidra 11.4.2 with improved transaction handling
- Update all Ghidra JAR dependencies to 11.4.2
- Improve TransactionHelper to properly handle endTransaction return value
- Add GHIDRA_HOME environment variable support for flexible builds
- Update version references in extension.properties and MANIFEST.MF

The transaction fix now checks the return value from endTransaction() and
properly reports transaction failures, providing better error handling for
Ghidra 11.3.2+ compatibility.

Refs #7
2025-11-11 13:01:47 +01:00

63 lines
2.3 KiB
Java

package eu.starsong.ghidra.util;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
import javax.swing.SwingUtilities;
import java.util.concurrent.atomic.AtomicReference;
public class TransactionHelper {
@FunctionalInterface
public interface GhidraSupplier<T> {
T get() throws Exception;
}
public static <T> T executeInTransaction(Program program, String transactionName, GhidraSupplier<T> operation)
throws TransactionException {
if (program == null) {
throw new IllegalArgumentException("Program cannot be null for transaction");
}
AtomicReference<T> result = new AtomicReference<>();
AtomicReference<Exception> exception = new AtomicReference<>();
try {
SwingUtilities.invokeAndWait(() -> {
int txId = -1;
boolean success = false;
try {
txId = program.startTransaction(transactionName);
if (txId < 0) {
throw new TransactionException("Failed to start transaction: " + transactionName);
}
result.set(operation.get());
success = true;
} catch (Exception e) {
exception.set(e);
Msg.error(TransactionHelper.class, "Transaction failed: " + transactionName, e);
} finally {
if (txId >= 0) {
if (!program.endTransaction(txId, success)) {
Msg.error(TransactionHelper.class, "Failed to end transaction: " + transactionName);
exception.set(new TransactionException("Failed to end transaction: " + transactionName));
}
}
}
});
} catch (Exception e) {
throw new TransactionException("Swing thread execution failed", e);
}
if (exception.get() != null) {
throw new TransactionException("Operation failed", exception.get());
}
return result.get();
}
public static class TransactionException extends Exception {
public TransactionException(String message) { super(message); }
public TransactionException(String message, Throwable cause) { super(message, cause); }
}
}