mirror of
https://github.com/kemko/nomad.git
synced 2026-01-04 17:35:43 +03:00
Merge pull request #4234 from hashicorp/b-4159
Fix race in StreamFramer and truncation in api/AllocFS.Logs
This commit is contained in:
@@ -338,15 +338,16 @@ func (s *HTTPServer) fsStreamImpl(resp http.ResponseWriter,
|
||||
return nil, CodedError(500, handlerErr.Error())
|
||||
}
|
||||
|
||||
p1, p2 := net.Pipe()
|
||||
decoder := codec.NewDecoder(p1, structs.MsgpackHandle)
|
||||
encoder := codec.NewEncoder(p1, structs.MsgpackHandle)
|
||||
// Create a pipe connecting the (possibly remote) handler to the http response
|
||||
httpPipe, handlerPipe := net.Pipe()
|
||||
decoder := codec.NewDecoder(httpPipe, structs.MsgpackHandle)
|
||||
encoder := codec.NewEncoder(httpPipe, structs.MsgpackHandle)
|
||||
|
||||
// Create a goroutine that closes the pipe if the connection closes.
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
p1.Close()
|
||||
httpPipe.Close()
|
||||
}()
|
||||
|
||||
// Create an output that gets flushed on every write
|
||||
@@ -355,10 +356,11 @@ func (s *HTTPServer) fsStreamImpl(resp http.ResponseWriter,
|
||||
// Create a channel that decodes the results
|
||||
errCh := make(chan HTTPCodedError)
|
||||
go func() {
|
||||
defer cancel()
|
||||
|
||||
// Send the request
|
||||
if err := encoder.Encode(args); err != nil {
|
||||
errCh <- CodedError(500, err.Error())
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -366,7 +368,6 @@ func (s *HTTPServer) fsStreamImpl(resp http.ResponseWriter,
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
errCh <- nil
|
||||
cancel()
|
||||
return
|
||||
default:
|
||||
}
|
||||
@@ -374,29 +375,29 @@ func (s *HTTPServer) fsStreamImpl(resp http.ResponseWriter,
|
||||
var res cstructs.StreamErrWrapper
|
||||
if err := decoder.Decode(&res); err != nil {
|
||||
errCh <- CodedError(500, err.Error())
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
decoder.Reset(httpPipe)
|
||||
|
||||
if err := res.Error; err != nil {
|
||||
if err.Code != nil {
|
||||
errCh <- CodedError(int(*err.Code), err.Error())
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := io.Copy(output, bytes.NewBuffer(res.Payload)); err != nil {
|
||||
if _, err := io.Copy(output, bytes.NewReader(res.Payload)); err != nil {
|
||||
errCh <- CodedError(500, err.Error())
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
handler(p2)
|
||||
handler(handlerPipe)
|
||||
cancel()
|
||||
codedErr := <-errCh
|
||||
|
||||
// Ignore EOF and ErrClosedPipe errors.
|
||||
if codedErr != nil &&
|
||||
(codedErr == io.EOF ||
|
||||
strings.Contains(codedErr.Error(), "closed") ||
|
||||
|
||||
Reference in New Issue
Block a user