Exceptions and GObject-based libraries

Hey all,

I've been tracking down bizarre bugs in some code I'm writing. In doing
so, I realized that my naive practice of throwing exceptions and
invoking continuations in a signal handler is incorrect.

The concrete reason is that signal_emit_unlocked_R in gsignal.c
allocates a data structure on the stack, references it from the heap,
assuming that it can dereference it when the function exits. If the
function performs a nonlocal exit, then gsignal.c still points to a
location on the stack, which will probably be clobbered later as the
stack grows. (Speaking of emission and g_recursive_emissions.)

This is unfortunate, and really reduces the expressivity of using
higher-level languages with gobject-based libraries. I seem to recall
that python uses different return values to implement exceptions, but I
know C++ has true non-local exits. I wanted to know how the rest of you
deal with this situation.

Also, I wanted to know if there's interest in at least making GObject
exception-safe. Gtk+ would take a lot more work, of course. This would
likely require explicit unwind blocks in a function, e.g.:

int state = 0;

myfun (void)
        G_BEGIN_UNWIND_PROTECT (myfun);

	state = 1;
	emit_my_signal ();

	G_UNWIND (myfun) {
		state = 0;

        G_END_UNWIND_PROTECT (myfun);
        return 10;

The expansion could be something like the following:

myfun (void)
        int _myfun_jumped;
        jmp_buf _myfun_jmp_buf;
        g_push_jmp_buf (&_myfun_jmp_buf);

	if ((_myfun_jumped = setjmp (_myfun_jmp_buf)))
		goto _myfun_unwind;

	state = 1;
	emit_my_signal ();

        g_pop_jmp_buf ();
		state = 0;

        if (_myfun_jumped)
		longjmp (*g_peek_jmp_buf (), -1);

        return 10;

The push/pop routines would have to keep a thread-local stack of jump
buffers for all of this to work. Then a language binding would have
to catch any uncaught exceptions coming from closures, call
`longjmp (g_peek_jmp_buf (), -1)' (which should probably be wrapped as
g_throw or something), and have a jmp buffer set up to catch uncaught
exceptions somewhere.

I'm afraid this is all too complicated, though. Portability would also
bite us pretty hard. But I see in the future a world in which few people
write their graphical applications in C. It would be a shame if all of
these higher-level languages would have to restrict themselves in order
to use Gtk+.

Any thoughts? Am I crazy?

Andy Wingo <wingo pobox com>

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