fix uncaught-exception-handler handling of non-escaping escape handler

and change the emergency error display handler to log and error
 Closes PR 11630
This commit is contained in:
Matthew Flatt 2011-01-20 14:00:44 -07:00
parent 0a56e0fc6a
commit 0c193a599a
3 changed files with 42 additions and 27 deletions

View File

@ -275,17 +275,18 @@ handler that reports both the original and newly raised exception).
The default uncaught-exception handler prints an error message using
the current @tech{error display handler} (see @racket[error-display-handler])
and then escapes by calling the current error escape handler (see
and then escapes by calling the current @tech{error escape handler} (see
@racket[error-escape-handler]). The call to each handler is
@racket[parameterize]d to set @racket[error-display-handler] to the
default @tech{error display handler}, and it is @racket[parameterize-break]ed
to disable breaks. The call to the error escape handler is further
to disable breaks. The call to the @tech{error escape handler} is further
parameterized to set @racket[error-escape-handler] to the default
error escape handler.
@tech{error escape handler}; if the @tech{error escape handler} returns, then
the default @tech{error escape handler} is called.
When the current @tech{error display handler} is the default handler, then the
error-display call is parameterized to install an emergency error
display handler that attempts to print directly to a console and never
display handler that logs an error (see @racket[log-error]) and never
fails.}
@defform[(with-handlers ([pred-expr handler-expr] ...)

View File

@ -1349,4 +1349,36 @@
; --------------------
;; Check that the default uncaught-exception handler falls
;; back to the default error escape handler if the current
;; one doesn't escape.
(test 'done
'error-non-escape-handler
(begin
(call-with-continuation-prompt
(lambda ()
(parameterize ([error-escape-handler void]
[error-display-handler void])
(raise 'oops))))
'done))
;; Check that if the current error port is broken,
;; so that the default error display handler fails,
;; then check that an error is logged.
(test #t
regexp-match?
#rx"output port is closed"
(let* ([p (open-output-bytes)]
[l (make-logger)]
[r (make-log-receiver l 'error)])
(close-output-port p)
(call-with-continuation-prompt
(lambda ()
(parameterize ([current-error-port p]
[current-logger l])
(raise 'ack))))
(vector-ref (sync r) 1)))
; --------------------
(report-errs)

View File

@ -661,23 +661,6 @@ void scheme_init_logger_config() {
scheme_set_root_param(MZCONFIG_LOGGER, (Scheme_Object *)scheme_main_logger);
}
static void
scheme_inescapeable_error(const char *a, const char *b)
{
int al, bl;
char *t;
al = strlen(a);
bl = strlen(b);
t = scheme_malloc_atomic(al + bl + 2);
memcpy(t, a, al);
memcpy(t + al, b, bl);
t[al + bl] = '\n';
t[al + bl + 1] = 0;
scheme_console_output(t, al + bl + 1);
}
static void
call_error(char *buffer, int len, Scheme_Object *exn)
{
@ -763,9 +746,8 @@ call_error(char *buffer, int len, Scheme_Object *exn)
scheme_pop_break_enable(&cframe2, 0);
scheme_pop_continuation_frame(&cframe);
/* Uh-oh; record the error and fall back to the default escaper */
scheme_inescapeable_error("error escape handler did not escape; calling the default error escape handler", "");
scheme_longjmp(savebuf, 1); /* force an exit */
/* Didn't escape, so fall back to the default escaper: */
def_error_escape_proc(0, NULL);
}
}
@ -2418,9 +2400,9 @@ emergency_error_display_proc(int argc, Scheme_Object *argv[])
s = scheme_char_string_to_byte_string(argv[0]);
scheme_console_output(SCHEME_BYTE_STR_VAL(s),
SCHEME_BYTE_STRTAG_VAL(s));
scheme_console_output("\n", 1);
scheme_log_message(NULL, SCHEME_LOG_ERROR,
SCHEME_BYTE_STR_VAL(s), SCHEME_BYTE_STRTAG_VAL(s),
scheme_false);
return scheme_void;
}