diff --git a/collects/drracket/private/init.rkt b/collects/drracket/private/init.rkt index 8bee64b9ab..2f3bad817b 100644 --- a/collects/drracket/private/init.rkt +++ b/collects/drracket/private/init.rkt @@ -31,24 +31,65 @@ (define system-security-guard (current-security-guard)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; + ;; internal error display support + ;; + + (define error-display-chan (make-channel)) + (thread + (λ () + (define-struct recent (msg when)) + (define currently-visible-chan (make-channel)) + (let loop ([recently-seen-errors/unfiltered '()] + [currently-visible #f]) + (sync + (handle-evt + error-display-chan + (λ (msg+exn) + (define recently-seen-errors + ;; recent errors are ones less than 5 minutes old + (let ([now (current-seconds)]) + (filter (λ (x) (<= (+ (recent-when x) (* 60 5)) now)) + recently-seen-errors/unfiltered))) + (define-values (msg exn) (apply values msg+exn)) + (cond + [currently-visible + ;; drop errors when we have one waiting to be clicked on + (loop recently-seen-errors #t)] + [(ormap (λ (x) (equal? msg (recent-msg x))) + recently-seen-errors) + ;; drop the error if we've seen it recently + (loop recently-seen-errors #f)] + [else + ;; show the error + (define title (error-display-handler-message-box-title)) + (define text (let ([p (open-output-string)]) + (parameterize ([current-error-port p] + [current-output-port p]) + (original-error-display-handler msg exn)) + (get-output-string p))) + + (parameterize ([current-eventspace error-display-eventspace] + [current-custodian system-custodian]) + (thread + (λ () + (message-box title text #f '(stop ok) #:dialog-mixin frame:focus-table-mixin) + (channel-put currently-visible #f)))) + (loop (cons (make-recent msg (current-seconds)) recently-seen-errors) + #t)]))) + (handle-evt + currently-visible-chan + (λ (val) + (loop recently-seen-errors/unfiltered #f))))))) + ;; override error-display-handler to duplicate the error ;; message in both the standard place (as defined by the ;; current error-display-handler) and in a message box ;; identifying the error as a drscheme internal error. (error-display-handler (λ (msg exn) - ;; this may raise an exception if the port is gone. (with-handlers ([exn:fail? (λ (x) (void))]) (original-error-display-handler msg exn)) - - (let ([title (error-display-handler-message-box-title)]) - (let ([text (let ([p (open-output-string)]) - (parameterize ([current-error-port p] - [current-output-port p]) - (original-error-display-handler msg exn)) - (get-output-string p))]) - - (parameterize ([current-custodian system-custodian]) - (parameterize ([current-eventspace error-display-eventspace]) - (message-box title text #f '(stop ok) #:dialog-mixin frame:focus-table-mixin))))))) + (channel-put error-display-chan (list msg exn))))