mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
Fix "send on closed channel" panic (#13745)
The httpStreamResponse should not return until CloseWithError has been called. Instead keep track of write state and skip writing/flushing if an error has occurred. Fixes #13743 Regression from #13597 (not released)
This commit is contained in:
parent
9ca25bd48f
commit
fe3e47b1e8
@ -951,44 +951,46 @@ func streamHTTPResponse(w http.ResponseWriter) *httpStreamResponse {
|
|||||||
blockCh := make(chan []byte)
|
blockCh := make(chan []byte)
|
||||||
h := httpStreamResponse{done: doneCh, block: blockCh}
|
h := httpStreamResponse{done: doneCh, block: blockCh}
|
||||||
go func() {
|
go func() {
|
||||||
defer close(doneCh)
|
var canWrite = true
|
||||||
|
write := func(b []byte) {
|
||||||
|
if canWrite {
|
||||||
|
n, err := w.Write(b)
|
||||||
|
if err != nil || n != len(b) {
|
||||||
|
canWrite = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ticker := time.NewTicker(time.Second * 10)
|
ticker := time.NewTicker(time.Second * 10)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
// Response not ready, write a filler byte.
|
// Response not ready, write a filler byte.
|
||||||
_, err := w.Write([]byte{32})
|
write([]byte{32})
|
||||||
if err != nil {
|
if canWrite {
|
||||||
return
|
|
||||||
}
|
|
||||||
w.(http.Flusher).Flush()
|
w.(http.Flusher).Flush()
|
||||||
|
}
|
||||||
case err := <-doneCh:
|
case err := <-doneCh:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_, werr := w.Write([]byte{1})
|
write([]byte{1})
|
||||||
if werr != nil {
|
write([]byte(err.Error()))
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Write([]byte(err.Error()))
|
|
||||||
} else {
|
} else {
|
||||||
w.Write([]byte{0})
|
write([]byte{0})
|
||||||
}
|
}
|
||||||
|
close(doneCh)
|
||||||
return
|
return
|
||||||
case block := <-blockCh:
|
case block := <-blockCh:
|
||||||
var tmp [5]byte
|
var tmp [5]byte
|
||||||
tmp[0] = 2
|
tmp[0] = 2
|
||||||
binary.LittleEndian.PutUint32(tmp[1:], uint32(len(block)))
|
binary.LittleEndian.PutUint32(tmp[1:], uint32(len(block)))
|
||||||
_, err := w.Write(tmp[:])
|
write(tmp[:])
|
||||||
if err != nil {
|
write(block)
|
||||||
return
|
if canWrite {
|
||||||
}
|
|
||||||
_, err = w.Write(block)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.(http.Flusher).Flush()
|
w.(http.Flusher).Flush()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
return &h
|
return &h
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user