Catching Haskell exceptions with gi-gtk and Reactive Banana
Asked Answered
F

1

9

My application is bug-free, of course, but just in case it contains any bottom values I want to put in a generic exception catcher which will at least pop up a message box to tell the user what kind of bug to report. Because I'm using gi-gtk I figured that any exceptions after initialisation will happen from inside the Gtk.main function, so the end of my main function looks looks something like this:

let executeProgram =
     catch Gtk.main $ \e -> do
           reportThisBugDialog $ show (e :: SomeException)
           -- Code here to try to recover to a known good state
           executeProgram
executeProgram

I'm also using Reactive Banana in case that is relevant, but this is outside the FRP code.

However this doesn't capture any exceptions. I put error "Test Exception" in the handler for "Help About", and my program just exited with a message printed to the console (which my users will not see of course).

How do I catch exceptions that occur inside my code when it is reacting to GTK signals?

Flock answered 23/5, 2018 at 13:56 Comment(2)
Great question. I suspect you're going to have to wrap each callback in a handler, as I believe callbacks get run in fresh Haskell threads (though still on the same OS thread as main, assuming Gtk.main itself is). Can you check whether that works for you? (I know it sucks...)Wheelhouse
@DanielWagner Its actually worse than that: almost all my callbacks do nothing more than fire off a Reactive Banana event. Quite what happens next in terms of call stacks and exception handling I'm not sure.Flock
Q
3

There is similar question here (though it is not specific to gi-gtk, so is a bit more general)t. Also I'd recommend this post.

Basically, haskell exceptions can't pass haskell/C border. Simply because C doesn't know anything about haskell exceptions.

In your case, Gtk.main runs gtk event loop, which is implemented in C, and callbacks are implemented in haskell. When callback throws haskell exception, it has to go through gtk event loop in order to reach executeProgram function. But it is impossible for the reason stated above.

I'm afraid, the solution is to catch all exceptions inside each callback. In your case, you probably can write a wrapper over on function from gi-gtk, which will catch all exceptions and show the bug dialog.

Quixotic answered 28/5, 2018 at 11:55 Comment(1)
Thanks for the explanation. I will try the wrapper you suggest.Flock

© 2022 - 2024 — McMap. All rights reserved.