Skip to content

Commit

Permalink
file: Fix race in closing
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelkarp committed Sep 27, 2016
1 parent ce2922f commit db46d9b
Showing 1 changed file with 16 additions and 5 deletions.
21 changes: 16 additions & 5 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type win32File struct {
handle syscall.Handle
wg sync.WaitGroup
closing bool
closingLock sync.RWMutex
readDeadline time.Time
writeDeadline time.Time
}
Expand All @@ -87,9 +88,12 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {

// closeHandle closes the resources associated with a Win32 handle
func (f *win32File) closeHandle() {
if !f.closing {
f.closingLock.Lock()
alreadyClosing := f.closing
f.closing = true
f.closingLock.Unlock()
if !alreadyClosing {
// cancel all IO and wait for it to complete
f.closing = true
cancelIoEx(f.handle, nil)
f.wg.Wait()
// at this point, no new IO can start
Expand All @@ -98,6 +102,12 @@ func (f *win32File) closeHandle() {
}
}

func (f *win32File) isClosing() bool {
f.closingLock.RLock()
defer f.closingLock.RUnlock()
return f.closing
}

// Close closes a win32File.
func (f *win32File) Close() error {
f.closeHandle()
Expand All @@ -108,7 +118,8 @@ func (f *win32File) Close() error {
// prepareIo prepares for a new IO operation
func (f *win32File) prepareIo() (*ioOperation, error) {
f.wg.Add(1)
if f.closing {
if f.isClosing() {
f.wg.Done()
return nil, ErrFileClosed
}
c := &ioOperation{}
Expand Down Expand Up @@ -142,7 +153,7 @@ func (f *win32File) asyncIo(c *ioOperation, deadline time.Time, bytes uint32, er
var r ioResult
wait := true
timedout := false
if f.closing {
if f.isClosing() {
cancelIoEx(f.handle, &c.o)
} else if !deadline.IsZero() {
now := time.Now()
Expand All @@ -166,7 +177,7 @@ func (f *win32File) asyncIo(c *ioOperation, deadline time.Time, bytes uint32, er
}
err = r.err
if err == syscall.ERROR_OPERATION_ABORTED {
if f.closing {
if f.isClosing() {
err = ErrFileClosed
} else if timedout {
err = ErrTimeout
Expand Down

0 comments on commit db46d9b

Please sign in to comment.