]> Cypherpunks repositories - gostls13.git/commitdiff
exp/inotify: prevent data race
authorJan Ziak <0xe2.0x9a.0x9b@gmail.com>
Mon, 25 Jun 2012 18:08:09 +0000 (14:08 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 25 Jun 2012 18:08:09 +0000 (14:08 -0400)
Fixes #3713.

R=bradfitz, rsc
CC=golang-dev
https://golang.org/cl/6331055

src/pkg/exp/inotify/inotify_linux.go

index 912cf5db820c672e72888aba96db8cf134907ec8..f989a9224d980e8f4fdd7c2a92f64ab7359b16a0 100644 (file)
@@ -31,6 +31,7 @@ import (
        "fmt"
        "os"
        "strings"
+       "sync"
        "syscall"
        "unsafe"
 )
@@ -47,6 +48,7 @@ type watch struct {
 }
 
 type Watcher struct {
+       mu       sync.Mutex
        fd       int               // File descriptor (as returned by the inotify_init() syscall)
        watches  map[string]*watch // Map of inotify watches (key: path)
        paths    map[int]string    // Map of watched paths (key: watch descriptor)
@@ -105,8 +107,12 @@ func (w *Watcher) AddWatch(path string, flags uint32) error {
                watchEntry.flags |= flags
                flags |= syscall.IN_MASK_ADD
        }
+
+       w.mu.Lock() // synchronize with readEvents goroutine
+
        wd, err := syscall.InotifyAddWatch(w.fd, path, flags)
        if err != nil {
+               w.mu.Unlock()
                return &os.PathError{
                        Op:   "inotify_add_watch",
                        Path: path,
@@ -118,6 +124,7 @@ func (w *Watcher) AddWatch(path string, flags uint32) error {
                w.watches[path] = &watch{wd: uint32(wd), flags: flags}
                w.paths[wd] = path
        }
+       w.mu.Unlock()
        return nil
 }
 
@@ -187,7 +194,9 @@ func (w *Watcher) readEvents() {
                        // doesn't append the filename to the event, but we would like to always fill the
                        // the "Name" field with a valid filename. We retrieve the path of the watch from
                        // the "paths" map.
+                       w.mu.Lock()
                        event.Name = w.paths[int(raw.Wd)]
+                       w.mu.Unlock()
                        if nameLen > 0 {
                                // Point "bytes" at the first byte of the filename
                                bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))