diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-04-06 06:31:11 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-04-06 06:31:11 -0700 |
commit | 9e4be16274554d469b64e5b240b04fe8549f8a1f (patch) | |
tree | 203677f307471db6df8861912b710d74e17771cd /unwind.c | |
parent | 49d82c3b34227ec0520eb1cf1bb22083453b49a7 (diff) | |
download | txr-9e4be16274554d469b64e5b240b04fe8549f8a1f.tar.gz txr-9e4be16274554d469b64e5b240b04fe8549f8a1f.tar.bz2 txr-9e4be16274554d469b64e5b240b04fe8549f8a1f.zip |
exceptions: unhandled non-error exceptions now return.
This patch makes a fundamental change in exception behavior.
Going forward, if an exception that is not derived from
error is not handled (no catch intercepts it, and no handler
accepts it) then the throw call simply returns nil to the
caller instead of unwinding and terminating the process.
For error exceptions, the behavior is the same: the
*uhandled-hook* is called, if it exists, and if it doesn't
exist or returns, unwinding and termination with diagnostics
ensues.
The rationale for not treating non-error exceptions fatally
is that this simplifies the use of code that throws exceptions
for non-error situations like progress updates. The code can
be used without the caller having to establish a handler.
* txr.1: Documentation updates and comaptibility notes.
* unwind.c (uw_rthrow): New returning throw function based on
the implementation of uw_throw.
(uw_rthrowv, uw_rthrowvf): New functions.
(uw_throw): Now a wrapper for uw_rthrow. Because uw_throw
still does not return, it calls abort if uw_rthrow
returns. uw_throw is used internally only for error
exceptions.
(uw_throwv, uw_throwfv): Functions removed.
(uw_late_init): Register throw and throwf to the
new functions uw_rthrowv an uw_rthrowfv.
* unwind.h (uw_rthrow, uw_rthrowv, uw_rthrowfv): Declared.
(uw_throwv, uw_throwfv): Declarations removed.
Diffstat (limited to 'unwind.c')
-rw-r--r-- | unwind.c | 54 |
1 files changed, 35 insertions, 19 deletions
@@ -658,7 +658,7 @@ static void invoke_handler(uw_frame_t *fr, struct args *args) uw_catch_end; } -val uw_throw(val sym, val args) +val uw_rthrow(val sym, val args) { uw_frame_t *ex; static int reentry_count = 0; @@ -705,18 +705,28 @@ val uw_throw(val sym, val args) } if (ex == 0) { - if (std_error == 0) { - fprintf(stderr, "txr: unhandled exception in early initialization\n"); - abort(); - } - if (uw_exception_subtype_p(sym, warning_s)) { --reentry_count; if (uw_exception_subtype_p(sym, defr_warning_s)) uw_defer_warning(args); - else + else if (std_error != 0) format(std_error, lit("warning: ~a\n"), car(args), nao); + if (!opt_compat || opt_compat >= 234) { + uw_rthrow(continue_s, nil); + return nil; + } uw_throw(continue_s, nil); + } + + if (!opt_compat || opt_compat >= 234) { + if (!uw_exception_subtype_p(sym, error_s)) { + --reentry_count; + return nil; + } + } + + if (std_error == 0) { + fprintf(stderr, "txr: unhandled exception in early initialization\n"); abort(); } @@ -746,9 +756,23 @@ val uw_throw(val sym, val args) abort(); } -val uw_throwv(val sym, struct args *arglist) +val uw_rthrowv(val sym, struct args *arglist) { - uw_throw(sym, args_get_list(arglist)); + return uw_rthrow(sym, args_get_list(arglist)); +} + +val uw_rthrowfv(val sym, val fmt, struct args *args) +{ + val stream = make_string_output_stream(); + (void) formatv(stream, fmt, args); + return uw_rthrow(sym, get_string_from_stream(stream)); + abort(); +} + +val uw_throw(val sym, val args) +{ + uw_rthrow(sym, args); + abort(); } val uw_throwf(val sym, val fmt, ...) @@ -764,14 +788,6 @@ val uw_throwf(val sym, val fmt, ...) abort(); } -val uw_throwfv(val sym, val fmt, struct args *args) -{ - val stream = make_string_output_stream(); - (void) formatv(stream, fmt, args); - uw_throw(sym, get_string_from_stream(stream)); - abort(); -} - val uw_errorf(val fmt, ...) { va_list vl; @@ -1280,8 +1296,8 @@ void uw_late_init(void) reg_mac(intern(lit("defex"), user_package), func_n2(me_defex)); reg_var(unhandled_hook_s = intern(lit("*unhandled-hook*"), user_package), nil); - reg_fun(throw_s, func_n1v(uw_throwv)); - reg_fun(intern(lit("throwf"), user_package), func_n2v(uw_throwfv)); + reg_fun(throw_s, func_n1v(uw_rthrowv)); + reg_fun(intern(lit("throwf"), user_package), func_n2v(uw_rthrowfv)); reg_fun(error_s, func_n1v(uw_errorfv)); reg_fun(intern(lit("purge-deferred-warning"), user_package), func_n1(uw_purge_deferred_warning)); |