aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/cli/internal/signals
diff options
context:
space:
mode:
Diffstat (limited to 'cli/internal/signals')
-rw-r--r--cli/internal/signals/signals.go60
1 files changed, 60 insertions, 0 deletions
diff --git a/cli/internal/signals/signals.go b/cli/internal/signals/signals.go
new file mode 100644
index 0000000..8634144
--- /dev/null
+++ b/cli/internal/signals/signals.go
@@ -0,0 +1,60 @@
+package signals
+
+import (
+ "os"
+ "os/signal"
+ "sync"
+ "syscall"
+)
+
+// Watcher watches for signals delivered to this process and provides
+// the opportunity for turbo to run cleanup
+type Watcher struct {
+ doneCh chan struct{}
+ closed bool
+ mu sync.Mutex
+ closers []func()
+}
+
+// AddOnClose registers a cleanup handler to run when a signal is received
+func (w *Watcher) AddOnClose(closer func()) {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ w.closers = append(w.closers, closer)
+}
+
+// Close runs the cleanup handlers registered with this watcher
+func (w *Watcher) Close() {
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ if w.closed {
+ return
+ }
+ w.closed = true
+ for _, closer := range w.closers {
+ closer()
+ }
+ w.closers = nil
+ close(w.doneCh)
+}
+
+// Done returns a channel that will be closed after all of the cleanup
+// handlers have been run.
+func (w *Watcher) Done() <-chan struct{} {
+ return w.doneCh
+}
+
+// NewWatcher returns a new Watcher instance for watching signals.
+func NewWatcher() *Watcher {
+ // TODO: platform specific signals to watch for?
+ signalCh := make(chan os.Signal, 1)
+ signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
+ w := &Watcher{
+ doneCh: make(chan struct{}),
+ }
+ go func() {
+ <-signalCh
+ w.Close()
+ }()
+ return w
+}