Skip to content

Commit

Permalink
Handle utf-8 conversion failures when piping values; fixes #715
Browse files Browse the repository at this point in the history
Although this commit increases the buffer size from 2048 to 8192, for
more speed, the other changes in this commit fix the problem even with
the original smaller buffer size. See comments for details.
  • Loading branch information
greghendershott committed Aug 24, 2024
1 parent 3cb49c5 commit 2ba2bd4
Showing 1 changed file with 26 additions and 7 deletions.
33 changes: 26 additions & 7 deletions racket/print.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,40 @@
(define (drain-value-pipe in out)
(flush-output out)
(close-output-port out)
(define buffer (make-bytes 2048))
(let loop ()
(match (read-bytes-avail! buffer in)
(let loop ([buffer (make-bytes 8192)]
[buffer-read-pos 0])
(match (read-bytes-avail! buffer in buffer-read-pos)
;; When read-bytes-avail! returns 0, it means there are bytes
;; available to read but no buffer space remaining. In that
;; case, grow the buffer, but just slightly -- the motivation
;; here is to accumulate just enough more bytes for utf-8
;; conversion to succeed. See next clause.
[0
(loop (bytes-append buffer (make-bytes 8))
(bytes-length buffer))]
[(? exact-nonnegative-integer? len)
(define v (bytes->string/utf-8 (subbytes buffer 0 len)))
(repl-output-value v)
(loop)]
;; When bytes->string/utf-8 fails, probably read-bytes-avail!
;; happened to return in the middle of reading a utf-8
;; sequence, so just try reading more. Above we'll grow the
;; buffer slightly if full.
(match (safe-bytes->string/utf-8 buffer len)
[(? string? s)
(repl-output-value s)
(loop buffer 0)]
[#f
(loop buffer (+ buffer-read-pos len))])]
[(? procedure? read-special)
;; m-p-w-specials ignores the position arguments so just pass
;; something satisfying the contract.
(define v (read-special #f #f #f 1))
(repl-output-value-special v)
(loop)]
(loop buffer 0)]
[(? eof-object?) (void)])))

(define (safe-bytes->string/utf-8 buffer len)
(with-handlers ([exn:fail:contract? (λ _ #f)])
(bytes->string/utf-8 buffer #f 0 len)))

;; pretty-print uses separate size and print hooks -- and the size
;; hook can even be called more than once per object. Avoid calling
;; convert-image two (or more!) times per object. That could be slow
Expand Down

0 comments on commit 2ba2bd4

Please sign in to comment.