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:
parent
0a56e0fc6a
commit
0c193a599a
|
@ -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 default uncaught-exception handler prints an error message using
|
||||||
the current @tech{error display handler} (see @racket[error-display-handler])
|
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[error-escape-handler]). The call to each handler is
|
||||||
@racket[parameterize]d to set @racket[error-display-handler] to the
|
@racket[parameterize]d to set @racket[error-display-handler] to the
|
||||||
default @tech{error display handler}, and it is @racket[parameterize-break]ed
|
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
|
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
|
When the current @tech{error display handler} is the default handler, then the
|
||||||
error-display call is parameterized to install an emergency error
|
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.}
|
fails.}
|
||||||
|
|
||||||
@defform[(with-handlers ([pred-expr handler-expr] ...)
|
@defform[(with-handlers ([pred-expr handler-expr] ...)
|
||||||
|
|
|
@ -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)
|
(report-errs)
|
||||||
|
|
|
@ -661,23 +661,6 @@ void scheme_init_logger_config() {
|
||||||
scheme_set_root_param(MZCONFIG_LOGGER, (Scheme_Object *)scheme_main_logger);
|
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
|
static void
|
||||||
call_error(char *buffer, int len, Scheme_Object *exn)
|
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_break_enable(&cframe2, 0);
|
||||||
scheme_pop_continuation_frame(&cframe);
|
scheme_pop_continuation_frame(&cframe);
|
||||||
|
|
||||||
/* Uh-oh; record the error and fall back to the default escaper */
|
/* Didn't escape, so fall back to the default escaper: */
|
||||||
scheme_inescapeable_error("error escape handler did not escape; calling the default error escape handler", "");
|
def_error_escape_proc(0, NULL);
|
||||||
scheme_longjmp(savebuf, 1); /* force an exit */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2418,9 +2400,9 @@ emergency_error_display_proc(int argc, Scheme_Object *argv[])
|
||||||
|
|
||||||
s = scheme_char_string_to_byte_string(argv[0]);
|
s = scheme_char_string_to_byte_string(argv[0]);
|
||||||
|
|
||||||
scheme_console_output(SCHEME_BYTE_STR_VAL(s),
|
scheme_log_message(NULL, SCHEME_LOG_ERROR,
|
||||||
SCHEME_BYTE_STRTAG_VAL(s));
|
SCHEME_BYTE_STR_VAL(s), SCHEME_BYTE_STRTAG_VAL(s),
|
||||||
scheme_console_output("\n", 1);
|
scheme_false);
|
||||||
|
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user