Data race: sharedPullerState WriteAt+Close
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -57,9 +58,22 @@ type pullerProgress struct {
|
|||||||
BytesTotal int64
|
BytesTotal int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A lockedWriterAt synchronizes WriteAt calls with an external mutex.
|
||||||
|
// WriteAt() is goroutine safe by itself, but not against for example Close().
|
||||||
|
type lockedWriterAt struct {
|
||||||
|
mut *sync.Mutex
|
||||||
|
wr io.WriterAt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w lockedWriterAt) WriteAt(p []byte, off int64) (n int, err error) {
|
||||||
|
w.mut.Lock()
|
||||||
|
defer w.mut.Unlock()
|
||||||
|
return w.wr.WriteAt(p, off)
|
||||||
|
}
|
||||||
|
|
||||||
// tempFile returns the fd for the temporary file, reusing an open fd
|
// tempFile returns the fd for the temporary file, reusing an open fd
|
||||||
// or creating the file as necessary.
|
// or creating the file as necessary.
|
||||||
func (s *sharedPullerState) tempFile() (*os.File, error) {
|
func (s *sharedPullerState) tempFile() (io.WriterAt, error) {
|
||||||
s.mut.Lock()
|
s.mut.Lock()
|
||||||
defer s.mut.Unlock()
|
defer s.mut.Unlock()
|
||||||
|
|
||||||
@@ -70,7 +84,7 @@ func (s *sharedPullerState) tempFile() (*os.File, error) {
|
|||||||
|
|
||||||
// If the temp file is already open, return the file descriptor
|
// If the temp file is already open, return the file descriptor
|
||||||
if s.fd != nil {
|
if s.fd != nil {
|
||||||
return s.fd, nil
|
return lockedWriterAt{&s.mut, s.fd}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the parent directory is writable. This is
|
// Ensure that the parent directory is writable. This is
|
||||||
@@ -106,7 +120,7 @@ func (s *sharedPullerState) tempFile() (*os.File, error) {
|
|||||||
// Same fd will be used by all writers
|
// Same fd will be used by all writers
|
||||||
s.fd = fd
|
s.fd = fd
|
||||||
|
|
||||||
return fd, nil
|
return lockedWriterAt{&s.mut, s.fd}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sourceFile opens the existing source file for reading
|
// sourceFile opens the existing source file for reading
|
||||||
|
|||||||
Reference in New Issue
Block a user