net/http-client: avoid race between EOF and collection close

The race condition can result in an "input port is closed"
error when a connection is used again.
This commit is contained in:
Matthew Flatt 2015-11-09 20:04:50 -07:00
parent 3d31d86bf5
commit 4c6750286a

View File

@ -184,9 +184,7 @@
(define (http-conn-response-port/chunked! hc #:close? [close? #f])
(define (http-pipe-chunk ip op)
(define (done)
(flush-output op)
(close-output-port op))
(define (done) (void))
(define crlf-bytes (make-bytes 2))
(let loop ([last-bytes #f])
(define in-v (read-line ip eol-type))
@ -248,11 +246,12 @@
(or (equal? method-bss #"HEAD")
(equal? method-bss "HEAD")
(equal? method-bss 'HEAD)))
(define raw-response-port
(define-values (raw-response-port wait-for-close?)
(cond
[head? (open-input-bytes #"")]
[head? (values (open-input-bytes #"") #f)]
[(regexp-member #rx#"^(?i:Transfer-Encoding: +chunked)$" headers)
(http-conn-response-port/chunked! hc #:close? #t)]
(values (http-conn-response-port/chunked! hc #:close? #t)
#t)]
[(ormap (λ (h)
(match (regexp-match #rx#"^(?i:Content-Length:) +(.+)$" h)
[#f #f]
@ -262,9 +261,10 @@
headers)
=>
(λ (count)
(http-conn-response-port/length! hc count #:close? close?))]
(values (http-conn-response-port/length! hc count #:close? close?)
close?))]
[else
(http-conn-response-port/rest! hc)]))
(values (http-conn-response-port/rest! hc) #t)]))
(define decoded-response-port
(cond
[head? raw-response-port]
@ -276,9 +276,13 @@
(thread
(λ ()
(gunzip-through-ports raw-response-port out))))
(thread
(thread
(λ ()
(thread-wait gunzip-t)
(when wait-for-close?
;; Wait for an EOF from the raw port before we
;; send an output on the decoding pipe:
(copy-port raw-response-port (open-output-nowhere)))
(close-output-port out)))
in]
[else