Custom exception handler

Hi,

I am looking for the global exception handler and a way to replace it with a custom one. The use case is a UI application (Gtk) where I want to catch all exceptions and let a message box pop up.

Thanks for any hint

Tobi

1 Like

There’s not really a global exception handler which seems relevant to what you’re doing. There’s one for code executed in the REPL, but I’m not sure that’s relevant for your application (and it can’t be swapped out in any case). There’s a fallback handler in the runtime, but that is reserved for reporting an internal crash dump when things really go wrong.

Why can’t you just put a try ... catch around the entry point(s) for the application code, and dispatch the errors from there to the UI?

1 Like

thanks for the suggestion but this is not really possible. Most of the code is within callbacks (see http://juliagraphics.github.io/Gtk.jl/latest/manual/signals.html) which are executed on a dedicated task. Putting try ... catch around any callback is lots of boilerplate code that I am trying to avoid.

What usually happens when you throw an exception from a GTK callback? If your julia callback is called by the GTK C code, either Gtk.jl should wrap it with an exception handler (in which case your question is a question about the way errors are reported by the Gtk.jl wrapper code), or the program will longjmp out of the GTK stack frames, likely corrupting the state of the C library (in which case you’ll have to add a try-catch yourself).

Looks like the former is the case by default: https://github.com/JuliaGraphics/Gtk.jl/blob/master/doc/more_signals.md#guarded so the answer lies in customizing the way exceptions are reported by Gtk.jl. Looking at the source, the default error handling there seems to be mostly hardcoded so you might need to customize that with your own @guarded-like thing, or modify Gtk.jl to make the default error handling more flexible.

Ok, thanks. The guarded thing is basically the try/catch around all callbacks.

But I would like to focus more on:

This has not so much tied to Gtk but the task machinery itself. What I observe is that sometimes the program crashed and sometimes nothing happens (no exception printed). I would argue that it would be better if the Julia runtime catches all exceptions. In C++ for instance all uncatched exceptions will call std::terminate which can be replaced.

If a random C library (call it libfoo; this can be gtk or something else entirely unrelated to julia) calls a callback which then calls longjmp, it’s very likely that the state of the data structures managed by libfoo will be corrupted. That is, unless libfoo has been explicitly and very carefully designed to be safe for this kind of thing which is fairly uncommon. There is nothing the julia task runtime can do about this; if you do throw an exception which skips over the stack frames of an external library anything may happen, including memory leaks, resource leaks, random segfaults hours later, or if you’re very lucky nothing bad at all. Don’t rely on it!

The julia runtime itself has been explicitly and carefully designed to be exception (currently implemented with longjmp) safe, but only for longjmps which are managed by julia itself. If you find a case where a native julia exception crashes the julia runtime (with or without a crash dump) this is a bug and should be reported. Just don’t mix julia exceptions in callbacks with external library code and expect it to work :wink: If you mixed C++ exceptions with C longjmp there’s a good chance of memory corruption etc, and std::terminate would never be called there either.

1 Like

As I have said, the callbacks are called from a Julia task

Under the hood, there is of cause some ccall involved but I don’t think this is relevant here. Its just a task and there are Julia exceptions (i.e. longjump) that should be caught by the runtime.

Of course, but the julia function gtk_main just immediately ccalls into libgtk itself.

https://github.com/JuliaGraphics/Gtk.jl/blob/17bfda1ea78a511cd39d58de56c09cadd93262fb/src/events.jl#L2

where to from there I’m not sure, but it seems like we have the situation gtk_main(julia) -> gtk_main(C) -> C -> ... -> C -> julia_callback