How to capture exceptions at physics thread?

I am trying to trap (in the code) exceptions on my code that is being run at physics thread (ex. pre physics tick), I want the application to hang if something happens there too.
I saw that all such exceptions are not critical, they just keep happening, until we look at the console to see them showing.
I would like to trap them and throw another so the IDE could stop on it and I could debug it.

I was trying to extend BulletAppState to try to capture them, but they seem to happen at PhysicsSpace.update(), the problem is that, I could override BulletAppState.startPhysics() and assign pSpace with my class, that is simple to “maintain” (copying from git updates jme31), but the problem is physics on my application is parallel, and so instantiated on a private startPhysicsOnExecutor() that is not extendable and much more complex…

any workaround to that? maybe reflection?

EDIT: a simple workaround here intercepting the logging API

Or, since the exceptions are in the pre physics tick of your own code you could simply wrap your code in a try/catch inside your listener.

1 Like

this “almost” worked:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
 throw new NullPointerException("uncaugcth exception, "+thread+", "+throwable);
}
});		

but physics thread traps are handled by ExecutionException that seems to handle NullPointerException

@pspeed I think that will suffice thx!
Btw, do you think a custom user exception to be delegated (where it traps ExecutionException) could work too? or could get too generalized?

I mean, you probably want to catch your exceptions anyway and forward them onto some kind of event bus that your app manages. (Or at least just call a static method somewhere that can deal with it.)

Some threads may have their own uncaught exception handlers then the default won’t work, etc… Really it’s nice when frameworks provide an error callback but when they don’t at least we can catch them ourselves.

1 Like

What you said is what I would really like to do!

And this is what I am doing:

A simple conditional breakpoint (Level.SEVERE.equals(this.level) (eclipse)) at:

LogRecord.LogRecord(){
  ...
  message = msg; //<---<< as `this.level` must have been set for the conditional breakpoint to work

It is helping on avoiding the humongous console log. I think I will try to make a console log reader to pause the application whenever some exception log happens and after that I just add many ignore regex.

Ummm… you know the whole point of proper logging APIs is to be able to filter on category and log level, right?

I thought you wanted to kill your app on error. Else just use regular logging and set your filtering properly.

1 Like

I think it is both problems, I was using System.out or System.err instead of Logger, good at least I was using a class for that, so I just fix it.

But also, whenever such logs happen, if they are severe, I want to be interrupted instead of staring clueless at the screen. That breakpoint helps on it.

I think I can redirect System.err and monitor it also, still researching.

http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/eventbus/EventBus.html

For anyone interested in stopping the application on any SEVERE log entry from any thread, you can add a handler basically like this:

class ExitHandler extends Handler{
	@Override
	public void publish(LogRecord record) {
		if(record.getLevel().equals(Level.SEVERE)){
			if(record.getThrown()!=null){
				System.exit(1);
			}
		}
	}

to all (available to the moment) loggers from this list:

LogManager.getLogManager().getLoggerNames()

and force some logger to exist beforehand with:

Logger.getLogger(fullClassNameGoHere);

@pspeed I didnt go on EventBus yet (there seems to have another also), but I believe the above code will have the same final result?

The only thing missing is that, for the Eclipse IDE to “auto-breakpoint” on the exception point seems simply impossible as it was trapped (may be it can, just didnt find how yet). So the workaround is still here to at least suspend on the message being logged, you can “drop to frame” but as the physics thread already provided an “exceptional” execution of the code, that cant be rolled-back, so just add the breakpoint where the real exception happened and wait next physics thread loop or run the application again.

Thoughts about the Logging API

I would like to add that, the logging API push me away from the beginning, the limitation of “log level” was a bad thing for me, I didnt know about categories tho. I wanted to see things considered low and high log level at the same time. And at that time I found it to be unnecessarily confusing (now it is more clear tho).

But worst, why I have to go thru a bloated log file if many of the warnings and errors are so similar (if not identical). So I decided to do my own logging in memory, I limited it by 100 log entries per kind (and I have added many kinds even TODO hehe), I can review them and dump more or less information, but most importantly, they are unique as much as possible, no repetitions! only the last entry have its values stored. I think the logging API should be like that by default. (may be it can do that, I just cant stand learning it right now :slight_smile: , my project goals are priority, but thx on the tip. May be if I release some library, it will use that API, may be not :slight_smile: ).

Also I believe I could adapt it to conform with the logging API, but I felt I would spend too much time in something I implemented an alternative in a few hours. Later on I can even adapt it to that API, so end users can use the global log options to control the way my application log will work,

Probably. Note: I generally recommend that people use Guava anyway so that event bus would have been free. As to the other you linked, it seems way more complicated than necessary for a simple event bus (that is already included in guava which most devs should already be using anyway).

Guava should really be included in Java and actually many of the things find there way over as time goes on.

As to the other, the point of logging is that you get some period of debug state along with the error depend on the log level. So many problems require seeing what happened over a loner period of time than just one frame or a few methods. Careful managed of log level, category, etc., are useful here. It’s a whole general philosophy, though. Any class that has something interesting to say gets a Logger at the top and can log whatever it wants… to the point that some critical infrastructure classes often log.trace() everything they do.

Having the ability to set log levels at runtime can then also be useful as if you’ve been playing your game for three hours and suddenly see this one odd thing happen when you shoot at the ducks or whatever… then you can up the log level, try again, keep doing it until you have the information you need. And it’s all right there in a file to refer to again and again as you work through the problem. I’ve even been known to cut and paste one or two lines of log output right into the code as comments where I’ve made some fix.

I do admit that the built in logging in Java is pretty abysmal, though. I hate it pretty hard and never use it myself… always use slf4j + some backend (log4j is my favorite but there is also logback)

Anyway, I still think using a “log” as a way to stop the application on an error is a little strange. Like using an exception to return things to a caller… yeah, it’s effective but it’s not really what it was meant for.

On the other hand, a simple error event bus can be a pretty useful of chaining things off of errors, fatal or otherwise. In my larger apps, I invariably have a few listeners registered, whether they do a dump of the thread stack, present an error pop-up to the user, or simply dump some other extra state.

But again, it’s largely based on a philosophy honed over years of dealing with very large and long-running applications.

1 Like