mirror of
https://github.com/containers/gvisor-tap-vsock.git
synced 2025-10-05 16:56:50 +08:00

fsnotify/fsnotify can't watch a folder that contains a symlink into a socket or named pipe. Use poll-based mechanism to watch the file for the time being until we find a better way or fix the issue in the upstream. Signed-off-by: Fata Nugraha <fatanugraha@outlook.com>
64 lines
1.2 KiB
Go
64 lines
1.2 KiB
Go
package utils
|
|
|
|
import (
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
// FileWatcher is an utility that
|
|
type FileWatcher struct {
|
|
path string
|
|
|
|
closeCh chan struct{}
|
|
pollInterval time.Duration
|
|
}
|
|
|
|
func NewFileWatcher(path string) *FileWatcher {
|
|
return &FileWatcher{
|
|
path: path,
|
|
pollInterval: 5 * time.Second, // 5s is the default inode cache timeout in linux for most systems.
|
|
closeCh: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
func (fw *FileWatcher) Start(changeHandler func()) {
|
|
prevModTime := fw.fileModTime(fw.path)
|
|
|
|
// use polling-based approach to detect file changes
|
|
// we can't use fsnotify/fsnotify due to issues with symlink+socket. see #462.
|
|
go func() {
|
|
for {
|
|
select {
|
|
case _, ok := <-fw.closeCh:
|
|
if !ok {
|
|
return // watcher is closed.
|
|
}
|
|
case <-time.After(fw.pollInterval):
|
|
}
|
|
|
|
modTime := fw.fileModTime(fw.path)
|
|
if modTime.IsZero() {
|
|
continue // file does not exists
|
|
}
|
|
|
|
if !prevModTime.Equal(modTime) {
|
|
changeHandler()
|
|
prevModTime = modTime
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (fw *FileWatcher) fileModTime(path string) time.Time {
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
return time.Time{}
|
|
}
|
|
|
|
return info.ModTime()
|
|
}
|
|
|
|
func (fw *FileWatcher) Stop() {
|
|
close(fw.closeCh)
|
|
}
|