Re: aborting the main loop




Espen S Johnsen <espejohn@online.no> writes:

> I think the current main loop code has some shortcomings when using gtk
> from languages with exception handling (Common Lisp in my case). The
> situasion is like this; if an exception thrown from inside a main loop
> is caught outside, the loop code will be left in an inconsistent
> state. When one tries to call gtk_main after this, warnings about main
> loop already active in another thread are printed.
> 
> After looking around in the code a bit, I came up with the following
> funcions which seems to work to clean up after an abort:

There is just no way that throwing an exception through GTK+
C code is going to work. I mean, maybe you can clean up the
main loop, but there may be memory allocated on the stack, or
a GTK+ function may depend on control returning to it.

(As a very common example, any time a GTK+ signal is called
the widget is referenced before calling the signal and 
unreferenced afterwards. If you jump through the unreference,
then you will leak the widget.)

I think the best you can do is effectively something like
(psuedo-code):

 struct LispMainLoop { GMainLoop loop, Exception thrown_exception }

 void main_run_stub (LispMainLoop loop) {
    loop.exception_thrown = NULL;
    push loop_stack, loop;
    g_main_run (loop.loop);
    if (loop.thrown_exception) {
      rethrow (loop.thrown_exception
    }
    pop loop_stack;
 }

 void callback_from_c () {
    lisp_push_unwind_protect();
    do_lisp_callback();
    loop_stack.top.exception = lisp_pop_unwind_protect();
    if (loop_stack.top.exception) 
      g_main_quit (loop_stack.top.loop);
 }

Well, I'm not sure that is clear, but the idea is that 
you do a g_main_quit() and propagate the exception. It
doesn't work perfectly because the C code can go ahead
and call more lisp callbacks after the exception has
been thrown, but it should handle a lot of cases,
and is the best you can do without adding EH to GTK+.

Regards,
                                        Owen



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]