diff --git a/etcdserver/api/v3rpc/maintenance.go b/etcdserver/api/v3rpc/maintenance.go index 076f7dad6..1d96e970a 100644 --- a/etcdserver/api/v3rpc/maintenance.go +++ b/etcdserver/api/v3rpc/maintenance.go @@ -117,11 +117,6 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance // used for integrity checks during snapshot restore operation h := sha256.New() - // buffer just holds read bytes from stream - // response size is multiple of OS page size, fetched in boltdb - // e.g. 4*1024 - buf := make([]byte, snapshotSendBufferSize) - sent := int64(0) total := snap.Size() size := humanize.Bytes(uint64(total)) @@ -132,6 +127,13 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance zap.String("size", size), ) for total-sent > 0 { + // buffer just holds read bytes from stream + // response size is multiple of OS page size, fetched in boltdb + // e.g. 4*1024 + // NOTE: srv.Send does not wait until the message is received by the client. + // Therefore the buffer can not be safely reused between Send operations + buf := make([]byte, snapshotSendBufferSize) + n, err := io.ReadFull(pr, buf) if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF { return togRPCError(err)