Engine left unusable, in the updating state, after an uncaught exception in a subsystem
Snack-a-Dog opened this issue · 1 comments
If an EntitySystem throws an uncaught exception in its update() method, the Engine is left in the updating state forever and can't be used ever again. Please use the following code to reproduce. After the initial "oopsie" exception, all further updates on the Engine will result in an "Cannot call update() on an Engine that is already updating" exception.
public class EngineExceptionTest extends ApplicationAdapter {
private Engine engine;
@Override
public void create () {
Gdx.app.setLogLevel(Application.LOG_DEBUG);
engine = new Engine();
// ...add bunch of systems
engine.addSystem(new SystemWithASubtleBug());
// ...add even more systems
// ...load the first level
}
@Override
public void render() {
try {
engine.update(0.1f);
} catch (Exception e) {
Gdx.app.log("fatal", "caught an unexpected exception", e);
// switch back to the main menu and try to continue
}
}
private static class SystemWithASubtleBug extends EntitySystem {
@Override
public void update(float deltaTime) {
// let's assume that this exception occurs only in very rare cases
throw new RuntimeException("oopsie");
}
}
}
Of course systems shouldn't throw any exceptions normally, but if one does because of some obscure bug, the Engine is essentially left dead, even though the application could still be able to continue. Currently possible workarounds include resetting the updating-field in the Engine to false via Reflection or creating a new Engine and copying the systems into it, both pretty nasty hacks.
A clean fix would be for the Engine to wrap the update loop over all systems into a try and to set "updating = false" (and maybe the componentOperationHandler/entityManager calls) in a finally block. The user of the class would then have the choice of trying to cope with the problem somehow or to let the exception kill the application.
Thanks for reporting, it should be available in the next snapshot build.