diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-10-10 23:22:42 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-10-10 23:22:42 -0700 |
commit | ec3ef435c68af026ddfca6fa312bde18077194b8 (patch) | |
tree | 74d73dedc3fdf652b3409e880d490b9fe475a36a /struct.c | |
parent | 46a525574121efd4e2ad5d1420d2ba11a67e9a1c (diff) | |
download | txr-ec3ef435c68af026ddfca6fa312bde18077194b8.tar.gz txr-ec3ef435c68af026ddfca6fa312bde18077194b8.tar.bz2 txr-ec3ef435c68af026ddfca6fa312bde18077194b8.zip |
Invoke finalizers if object initialization bails.
* struct.c (make_struct): Add unwind protection around
the initialization of the struct object, which calls
the partially initialized object's finalizers if
initialization is abandoned by a non-local exit.
* txr.1: Document the behavior, under make-struct and
the new macro.
Diffstat (limited to 'struct.c')
-rw-r--r-- | struct.c | 12 |
1 files changed, 12 insertions, 0 deletions
@@ -339,6 +339,7 @@ val make_struct(val type, val plist, struct args *args) size_t size = offsetof(struct struct_inst, slot) + sizeof (val) * nslots; struct struct_inst *si = coerce(struct struct_inst *, chk_malloc(size)); val sinst; + volatile val inited = nil; if (args_more(args, 0) && !st->boactor) { free(si); @@ -357,6 +358,8 @@ val make_struct(val type, val plist, struct args *args) si->type = type; + uw_simple_catch_begin; + call_initfun_chain(st, sinst); for (; plist; plist = cddr(plist)) @@ -369,6 +372,15 @@ val make_struct(val type, val plist, struct args *args) generic_funcall(st->boactor, args_copy); } + inited = t; + + uw_unwind { + if (!inited) + gc_call_finalizers(sinst); + } + + uw_catch_end; + return sinst; } } |