Exceptions and GObject-based libraries

Andy Wingo <[email protected]>
Newsgroups gmane.comp.gnome.language-bindings
Message-ID <20040827121010.GA4989@lark>
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;

int
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:

int
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 ();

_myfun_unwind:
        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 <[email protected]>
http://ambient.2y.net/wingo/
_______________________________________________
language-bindings mailing list  [email protected]
http://mail.gnome.org/mailman/listinfo/language-bindings
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.