From c57b87d6d43c278238e4b06d360a90805f3d8ea8 Mon Sep 17 00:00:00 2001 From: Darren Stahl Date: Thu, 3 Aug 2017 15:26:45 -0700 Subject: [PATCH] Prevent adding to a sync.WaitGroup that has a waiter Signed-off-by: Darren Stahl --- file.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/file.go b/file.go index 2a311d1f..99cc07fb 100644 --- a/file.go +++ b/file.go @@ -78,6 +78,7 @@ func initIo() { type win32File struct { handle syscall.Handle wg sync.WaitGroup + wgLock sync.RWMutex closing atomicBool readDeadline deadlineHandler writeDeadline deadlineHandler @@ -118,7 +119,9 @@ func (f *win32File) closeHandle() { if !f.closing.swap(true) { // cancel all IO and wait for it to complete cancelIoEx(f.handle, nil) + f.wgLock.Lock() f.wg.Wait() + f.wgLock.Unlock() // at this point, no new IO can start syscall.Close(f.handle) f.handle = 0 @@ -134,10 +137,13 @@ func (f *win32File) Close() error { // prepareIo prepares for a new IO operation. // The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. func (f *win32File) prepareIo() (*ioOperation, error) { + f.wgLock.RLock() if f.closing.isSet() { + f.wgLock.RUnlock() return nil, ErrFileClosed } f.wg.Add(1) + f.wgLock.RUnlock() c := &ioOperation{} c.ch = make(chan ioResult) return c, nil