Set up crash reporting for Guava's EventBuses
- Added GuavaEventBusHijacker to access an inexplicably package-private constructor in EventBus - Added and utilized ReportingEventBus that reports caught exceptions
This commit is contained in:
parent
c919ffc8ce
commit
1bba20504d
@ -22,10 +22,11 @@ import org.lwjgl.glfw.GLFW;
|
|||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
import ru.windcorp.progressia.client.graphics.input.*;
|
import ru.windcorp.progressia.client.graphics.input.*;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
|
||||||
|
|
||||||
public class InputHandler {
|
public class InputHandler {
|
||||||
|
|
||||||
private static final EventBus INPUT_EVENT_BUS = new EventBus("Input");
|
private static final EventBus INPUT_EVENT_BUS = ReportingEventBus.create("Input");
|
||||||
|
|
||||||
// KeyEvent
|
// KeyEvent
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ import ru.windcorp.progressia.client.graphics.input.bus.InputBus;
|
|||||||
import ru.windcorp.progressia.client.graphics.input.bus.InputListener;
|
import ru.windcorp.progressia.client.graphics.input.bus.InputListener;
|
||||||
import ru.windcorp.progressia.common.util.Named;
|
import ru.windcorp.progressia.common.util.Named;
|
||||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
|
||||||
|
|
||||||
public class Component extends Named {
|
public class Component extends Named {
|
||||||
|
|
||||||
@ -455,7 +456,7 @@ public class Component extends Named {
|
|||||||
|
|
||||||
public void addListener(Object listener) {
|
public void addListener(Object listener) {
|
||||||
if (eventBus == null) {
|
if (eventBus == null) {
|
||||||
eventBus = new EventBus(getName());
|
eventBus = ReportingEventBus.create(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
eventBus.register(listener);
|
eventBus.register(listener);
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package ru.windcorp.progressia.common.hacks;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.EventBus;
|
||||||
|
import com.google.common.eventbus.SubscriberExceptionHandler;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class had to be written because there is not legal way to instantiate a non-async
|
||||||
|
* {@link EventBus} with both a custom identifier and a custom exception handler. Which
|
||||||
|
* is a shame. Guava maintainers know about the issue but have rejected solutions multiple
|
||||||
|
* times <em>without a clearly stated reason</em>; looks like some dirty reflection will
|
||||||
|
* have to do.
|
||||||
|
* @author javapony
|
||||||
|
*/
|
||||||
|
public class GuavaEventBusHijacker {
|
||||||
|
|
||||||
|
public static final Constructor<EventBus> THE_CONSTRUCTOR;
|
||||||
|
public static final Method DISPATCHER__PER_THREAD_DISPATCH_QUEUE;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Class<?> dispatcherClass = Class.forName("com.google.common.eventbus.Dispatcher");
|
||||||
|
|
||||||
|
THE_CONSTRUCTOR = EventBus.class.getDeclaredConstructor(
|
||||||
|
String.class, Executor.class, dispatcherClass, SubscriberExceptionHandler.class
|
||||||
|
);
|
||||||
|
THE_CONSTRUCTOR.setAccessible(true);
|
||||||
|
|
||||||
|
DISPATCHER__PER_THREAD_DISPATCH_QUEUE = dispatcherClass.getDeclaredMethod("perThreadDispatchQueue");
|
||||||
|
DISPATCHER__PER_THREAD_DISPATCH_QUEUE.setAccessible(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw CrashReports.report(e, "Something went horribly wrong when setting up EventBus hijacking. Has Guava updated?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EventBus newEventBus(String identifier, SubscriberExceptionHandler exceptionHandler) {
|
||||||
|
try {
|
||||||
|
return THE_CONSTRUCTOR.newInstance(
|
||||||
|
identifier,
|
||||||
|
MoreExecutors.directExecutor(),
|
||||||
|
DISPATCHER__PER_THREAD_DISPATCH_QUEUE.invoke(null),
|
||||||
|
exceptionHandler
|
||||||
|
);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw CrashReports.report(e, "Something went horribly wrong when hijacking EventBus. Has Guava updated?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package ru.windcorp.progressia.common.util.crash;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.hacks.GuavaEventBusHijacker;
|
||||||
|
|
||||||
|
public class ReportingEventBus {
|
||||||
|
|
||||||
|
private ReportingEventBus() {}
|
||||||
|
|
||||||
|
public static EventBus create(String identifier) {
|
||||||
|
return GuavaEventBusHijacker.newEventBus(identifier, (throwable, context) -> {
|
||||||
|
// Makes sense to append identifier to messageFormat because different EventBuses are completely unrelated
|
||||||
|
throw CrashReports.crash(throwable, "Unexpected exception in EventBus " + identifier);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user