diff --git a/collects/scribblings/reference/exns.scrbl b/collects/scribblings/reference/exns.scrbl index 05e2bada50..0ee8dde363 100644 --- a/collects/scribblings/reference/exns.scrbl +++ b/collects/scribblings/reference/exns.scrbl @@ -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] ...) diff --git a/collects/tests/racket/thread.rktl b/collects/tests/racket/thread.rktl index 605c4b142e..a3063fd688 100644 --- a/collects/tests/racket/thread.rktl +++ b/collects/tests/racket/thread.rktl @@ -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) diff --git a/src/racket/src/error.c b/src/racket/src/error.c index 4b6b3f7dfd..e11b936ac9 100644 --- a/src/racket/src/error.c +++ b/src/racket/src/error.c @@ -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; }