1
0
mirror of https://github.com/golang/go synced 2024-11-26 00:07:57 -07:00

exp/inotify: prevent data race

Fixes #3713.

R=bradfitz, rsc
CC=golang-dev
https://golang.org/cl/6331055
This commit is contained in:
Jan Ziak 2012-06-25 14:08:09 -04:00 committed by Russ Cox
parent 5e75337c4e
commit b3382ec9e9

View File

@ -31,6 +31,7 @@ import (
"fmt" "fmt"
"os" "os"
"strings" "strings"
"sync"
"syscall" "syscall"
"unsafe" "unsafe"
) )
@ -47,6 +48,7 @@ type watch struct {
} }
type Watcher struct { type Watcher struct {
mu sync.Mutex
fd int // File descriptor (as returned by the inotify_init() syscall) fd int // File descriptor (as returned by the inotify_init() syscall)
watches map[string]*watch // Map of inotify watches (key: path) watches map[string]*watch // Map of inotify watches (key: path)
paths map[int]string // Map of watched paths (key: watch descriptor) 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 watchEntry.flags |= flags
flags |= syscall.IN_MASK_ADD flags |= syscall.IN_MASK_ADD
} }
w.mu.Lock() // synchronize with readEvents goroutine
wd, err := syscall.InotifyAddWatch(w.fd, path, flags) wd, err := syscall.InotifyAddWatch(w.fd, path, flags)
if err != nil { if err != nil {
w.mu.Unlock()
return &os.PathError{ return &os.PathError{
Op: "inotify_add_watch", Op: "inotify_add_watch",
Path: path, 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.watches[path] = &watch{wd: uint32(wd), flags: flags}
w.paths[wd] = path w.paths[wd] = path
} }
w.mu.Unlock()
return nil 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 // 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 "Name" field with a valid filename. We retrieve the path of the watch from
// the "paths" map. // the "paths" map.
w.mu.Lock()
event.Name = w.paths[int(raw.Wd)] event.Name = w.paths[int(raw.Wd)]
w.mu.Unlock()
if nameLen > 0 { if nameLen > 0 {
// Point "bytes" at the first byte of the filename // Point "bytes" at the first byte of the filename
bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent])) bytes := (*[syscall.PathMax]byte)(unsafe.Pointer(&buf[offset+syscall.SizeofInotifyEvent]))