mirror of
https://github.com/minio/minio.git
synced 2025-03-31 09:43:43 -04:00
Avoid CompleteMultipart freeze with unexpected network issue (#15102)
If sending a white space during a long S3 handler call fails, the whitespace goroutine forgets to return a result to the caller. Therefore, the complete multipart handler will be blocked. Remember to send the header written result to the caller or/and close the channel.
This commit is contained in:
parent
5d23be6242
commit
98ddc3596c
@ -3101,10 +3101,12 @@ func (w *whiteSpaceWriter) WriteHeader(statusCode int) {
|
|||||||
// we do background append as and when the parts arrive and completeMultiPartUpload
|
// we do background append as and when the parts arrive and completeMultiPartUpload
|
||||||
// is quick. Only in a rare case where parts would be out of order will
|
// is quick. Only in a rare case where parts would be out of order will
|
||||||
// FS:completeMultiPartUpload() take a longer time.
|
// FS:completeMultiPartUpload() take a longer time.
|
||||||
func sendWhiteSpace(w http.ResponseWriter) <-chan bool {
|
func sendWhiteSpace(ctx context.Context, w http.ResponseWriter) <-chan bool {
|
||||||
doneCh := make(chan bool)
|
doneCh := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
|
defer close(doneCh)
|
||||||
ticker := time.NewTicker(time.Second * 10)
|
ticker := time.NewTicker(time.Second * 10)
|
||||||
|
defer ticker.Stop()
|
||||||
headerWritten := false
|
headerWritten := false
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -3124,7 +3126,8 @@ func sendWhiteSpace(w http.ResponseWriter) <-chan bool {
|
|||||||
}
|
}
|
||||||
w.(http.Flusher).Flush()
|
w.(http.Flusher).Flush()
|
||||||
case doneCh <- headerWritten:
|
case doneCh <- headerWritten:
|
||||||
ticker.Stop()
|
return
|
||||||
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3298,7 +3301,7 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite
|
|||||||
}
|
}
|
||||||
|
|
||||||
w = &whiteSpaceWriter{ResponseWriter: w, Flusher: w.(http.Flusher)}
|
w = &whiteSpaceWriter{ResponseWriter: w, Flusher: w.(http.Flusher)}
|
||||||
completeDoneCh := sendWhiteSpace(w)
|
completeDoneCh := sendWhiteSpace(ctx, w)
|
||||||
objInfo, err := completeMultiPartUpload(ctx, bucket, object, uploadID, complMultipartUpload.Parts, opts)
|
objInfo, err := completeMultiPartUpload(ctx, bucket, object, uploadID, complMultipartUpload.Parts, opts)
|
||||||
// Stop writing white spaces to the client. Note that close(doneCh) style is not used as it
|
// Stop writing white spaces to the client. Note that close(doneCh) style is not used as it
|
||||||
// can cause white space to be written after we send XML response in a race condition.
|
// can cause white space to be written after we send XML response in a race condition.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user