From b31d51e0b16f6233f2285adbab674ecfa2ace4ff Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 5 Sep 2015 13:59:36 -0600 Subject: inotify: Avoid most of the race conditions, get rid of Cint There's still a condition that could be a race with fd-reuse, if one goroutine is calling inotify.{AddWatch,RmWatch,Read}(); another goroutine is calling inotify.Close(), and several things happen between loadFd() running and the add_watch/rm_watch/read syscall launching: - syscall.Close() returns - syscall.Open() reuses the filedescriptor A B syscall(loadFd()) inotify.Close(); syscall.Open() ---------------------------------------------------------- loadFd() syscall.Close() syscall.Open() syscall() Given that Read() can't be allowed to block Close() from running, I'm not sure there's a way to fix this. --- inotify/bits.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'inotify/bits.go') diff --git a/inotify/bits.go b/inotify/bits.go index 3606b52..9162435 100644 --- a/inotify/bits.go +++ b/inotify/bits.go @@ -1,5 +1,7 @@ package inotify +import "sync/atomic" + const ( // Flags for the parameter of InotifyInit1(). // These, oddly, appear to be 24-bit numbers. @@ -7,8 +9,19 @@ const ( IN_NONBLOCK uint32 = 00004000 ) -type Mask uint32 +// Logically, Fd and Wd should be 'int', not 'int64', to match the OS. +// But, because there's no 'sync/atomic.SwapInt', we cast up to int64. +type Wd int64 +type Fd int64 + +func swapFd(addr *Fd, new Fd) (old Fd) { + return Fd(atomic.SwapInt64((*int64)(addr), int64(new))) +} +func loadFd(addr *Fd) Fd { + return Fd(atomic.LoadInt64((*int64)(addr))) +} +type Mask uint32 const ( // Supported events suitable for the `mask` parameter of Inotify.AddWatch(). IN_ACCESS Mask = (1<< 0) // File was accessed. -- cgit v1.2.3