From 1362aae61a29991a5108c6ddfb4ba5a28eb867c6 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 17 Jul 2019 21:49:51 -0400 Subject: [PATCH] Gracefully handle SIGINT --- beemer.go | 18 +++++++++++++----- cli.go | 16 +++++++++++----- util.go | 11 +++++++++++ 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/beemer.go b/beemer.go index b31c9c4..1106e4e 100644 --- a/beemer.go +++ b/beemer.go @@ -6,6 +6,8 @@ import ( "os" "os/exec" "path/filepath" + "sync" + "syscall" "time" ) @@ -16,6 +18,7 @@ type Beemer struct { beemChan chan string watcher *fsnotify.Watcher inactiveDelay time.Duration + globalWg *sync.WaitGroup } type File struct { @@ -132,12 +135,11 @@ func (b Beemer) handleWatcherEvents() { } func (b Beemer) work() { - for { - select { - case name := <-b.beemChan: - b.beemFile(name) - } + b.globalWg.Add(1) + for name := range b.beemChan { + b.beemFile(name) } + b.globalWg.Done() } func (b Beemer) handleFileInactive(t *time.Timer, name string) { @@ -159,6 +161,12 @@ func (b Beemer) beemFile(filename string) { name, args := b.beemCommand(newName, filepath.Dir(filename)) cmd := exec.Command(name, args...) + + // Don't send SIGINT to child processes + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + } + out, err := cmd.CombinedOutput() if err != nil { logrus.WithField("name", filename).WithError(err).Error(string(out)) diff --git a/cli.go b/cli.go index a0d057e..8ff69cc 100644 --- a/cli.go +++ b/cli.go @@ -6,10 +6,14 @@ import ( "github.com/sirupsen/logrus" "github.com/urfave/cli" "os" + "os/signal" + "sync" + "syscall" "time" ) func globalInit() { + //TODO cmdline flag logrus.SetLevel(logrus.TraceLevel) } @@ -66,14 +70,13 @@ func main() { beemChan: make(chan string, transfers), beemCommand: parseCommand(cmdString), inactiveDelay: inactiveDelay, + globalWg: &sync.WaitGroup{}, } beemer.initTempDir() beemer.watcher, _ = fsnotify.NewWatcher() - defer beemer.dispose() - go beemer.handleWatcherEvents() beemer.initWatchDir(watchDir) @@ -82,10 +85,13 @@ func main() { go beemer.work() } - //TODO gracefully handle SIGINT - done := make(chan bool) - <-done + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT) + defer beemer.dispose() + + <-sigChan + logrus.Info("Received SIGINT") return nil } diff --git a/util.go b/util.go index d91d141..865c6e8 100644 --- a/util.go +++ b/util.go @@ -108,8 +108,19 @@ func isDir(name string) bool { func (b Beemer) dispose() { b.watcher.Close() + close(b.beemChan) + + logrus.WithField("chanLen", len(b.beemChan)).Info("Waiting for beem queue to drain...") + <-b.beemChan + + logrus.Info("Waiting for current commands to finish...") + b.globalWg.Wait() + + logrus.Info("Cleaning up temp dir...") err := os.RemoveAll(b.tempDir) if err != nil { logrus.Fatal(err) } + + logrus.Info("Goodbye.") }