summaryrefslogtreecommitdiff
path: root/src/nshd/hackers_git/hackers_watch.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2015-09-12 09:14:40 -0600
committerLuke Shumaker <lukeshu@sbcglobal.net>2015-09-12 09:14:40 -0600
commitb190157b8c568922f7f9b4039b67a34862fa9f54 (patch)
tree41890a5470e013c31e89d00fe6a134434f3417d4 /src/nshd/hackers_git/hackers_watch.go
parenta71e76c9ab160f0ab7abbfe6db500b3b178e57de (diff)
Add an inotify watcher utility using channels; use it.
The interface of inotify/inutil.Watcher more resembles golang.org/x/exp/inotify; with it using channels instead of repeated calls to Read(). In my use-case, this is useful because it allows implementing a "read" (select, really) that doesn't block Close(); which is required to handle the TERM signal correctly.
Diffstat (limited to 'src/nshd/hackers_git/hackers_watch.go')
-rw-r--r--src/nshd/hackers_git/hackers_watch.go110
1 files changed, 65 insertions, 45 deletions
diff --git a/src/nshd/hackers_git/hackers_watch.go b/src/nshd/hackers_git/hackers_watch.go
index c10ec78..666237b 100644
--- a/src/nshd/hackers_git/hackers_watch.go
+++ b/src/nshd/hackers_git/hackers_watch.go
@@ -2,6 +2,7 @@ package hackers_git
import (
"inotify"
+ "inotify/inutil"
"os"
"path/filepath"
"sd_daemon/logger"
@@ -49,6 +50,7 @@ func (o *Hackers) unwatchHomedir(wd inotify.Wd) {
func (o *Hackers) close() {
if o.in_fd != nil {
o.in_fd.Close()
+ defer o.workers.Wait()
}
o.in_wd_home = -1
o.in_wd_yaml = -1
@@ -60,7 +62,7 @@ func (o *Hackers) close() {
func (o *Hackers) reload() (err error) {
o.close()
- o.in_fd, err = inotify.InotifyInit() ; if err != nil { return }
+ o.in_fd, err = inutil.WatcherInit() ; if err != nil { return }
o.in_wd_home, err = o.in_fd.AddWatch("/home" , in_DIR|in_CHILD_ADD); if err != nil { return }
o.in_wd_yaml, err = o.in_fd.AddWatch(o.Cfg.Yamldir, in_DIR|in_CHILD_ANY); if err != nil { return }
@@ -73,6 +75,12 @@ func (o *Hackers) reload() (err error) {
o.load_yaml_file(filename, false)
}
+ go func() {
+ defer lsb.Recover()
+ defer o.workers.Done()
+ o.worker()
+ }()
+
err = nil
return
}
@@ -160,55 +168,67 @@ func (o *Hackers) worker() {
if err != nil {
worker_error("failed to load %q: %v", o.Cfg.Yamldir, err)
}
- for event, err := o.in_fd.Read(); err == nil; event, err = o.in_fd.Read() {
- switch event.Wd {
- case o.in_wd_yaml:
- // handle updates to yaml files
- if event.Mask&in_DIR_INVALID != 0 {
- err := o.Reload()
- if err != nil {
- worker_error("failed to reload hackers.git yaml directory: %v", err)
-
- }
- err = os.Chdir(o.Cfg.Yamldir)
- if err != nil {
- worker_error("failed to load %q: %v", o.Cfg.Yamldir, err)
+Loop:
+ for {
+ select {
+ case event, ok := <-o.in_fd.Events:
+ if !ok {
+ break Loop
+ }
+ switch event.Wd {
+ case o.in_wd_yaml:
+ // handle updates to yaml files
+ if event.Mask&in_DIR_INVALID != 0 {
+ err := o.Reload()
+ if err != nil {
+ worker_error("failed to reload hackers.git yaml directory: %v", err)
+
+ }
+ err = os.Chdir(o.Cfg.Yamldir)
+ if err != nil {
+ worker_error("failed to load %q: %v", o.Cfg.Yamldir, err)
+ }
+ } else if event.Mask&in_CHILD_ANY != 0 {
+ if event.Name == nil {
+ panic("recieved child event from inotify, but no child name")
+ }
+ o.load_yaml_file(o.Cfg.Yamldir + "/" + *event.Name, true)
+ } else {
+ panic("recieved non-subscribed inotify event from kernel")
}
- } else if event.Mask&in_CHILD_ANY != 0 {
- if event.Name == nil {
- panic("recieved child event from inotify, but no child name")
+ case o.in_wd_home:
+ if event.Mask&in_DIR_INVALID != 0 {
+ err := o.Reload()
+ if err != nil {
+ panic(err)
+ }
+ } else if event.Mask&inotify.IN_ISDIR != 0 {
+ // handle added home directory
+ o.worker_watch_homedirs()
}
- o.load_yaml_file(o.Cfg.Yamldir + "/" + *event.Name, true)
- } else {
- panic("recieved non-subscribed inotify event from kernel")
- }
- case o.in_wd_home:
- if event.Mask&in_DIR_INVALID != 0 {
- err := o.Reload()
- if err != nil {
- panic(err)
+ default:
+ // handle a change to someone's password
+ if event.Mask&in_DIR_INVALID != 0 {
+ o.unwatchHomedir(event.Wd)
+ o.worker_watch_homedirs()
+ } else if event.Name != nil {
+ if *event.Name == ".password" {
+ func() {
+ o.lock.Lock()
+ defer o.lock.Unlock()
+ o.load_user_password(o.in_wd2uid[event.Wd])
+ }()
+ }
+ } else {
+ logger.Debug("hackers.git: event didn't match: %#v", event)
}
- } else if event.Mask&inotify.IN_ISDIR != 0 {
- // handle added home directory
- o.worker_watch_homedirs()
}
- default:
- // handle a change to someone's password
- if event.Mask&in_DIR_INVALID != 0 {
- o.unwatchHomedir(event.Wd)
- o.worker_watch_homedirs()
- } else if event.Name != nil {
- if *event.Name == ".password" {
- func() {
- o.lock.Lock()
- defer o.lock.Unlock()
- o.load_user_password(o.in_wd2uid[event.Wd])
- }()
- }
- } else {
- logger.Debug("hackers.git: event didn't match: %#v", event)
+ case err, ok := <-o.in_fd.Errors:
+ if !ok {
+ break Loop
}
+ logger.Warning("hackers.git: inotify error: %v", err)
}
}
- logger.Info("Stopped hackers.git inotify watcher")
+ logger.Info("hackers.git: Stopped inotify watcher")
}