2017-07-10 17:32:42 +02:00
|
|
|
package host
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"os/signal"
|
|
|
|
"sync"
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
|
|
|
// package-level interrupt notifier and event firing.
|
|
|
|
|
|
|
|
type world struct {
|
|
|
|
mu sync.Mutex
|
|
|
|
// onInterrupt contains a list of the functions that should be called when CTRL+C/CMD+C or
|
|
|
|
// a unix kill command received.
|
|
|
|
onInterrupt []func()
|
|
|
|
}
|
|
|
|
|
|
|
|
var w = &world{}
|
|
|
|
|
|
|
|
// RegisterOnInterrupt registers a global function to call when CTRL+C/CMD+C pressed or a unix kill command received.
|
|
|
|
func RegisterOnInterrupt(cb func()) {
|
|
|
|
w.mu.Lock()
|
|
|
|
w.onInterrupt = append(w.onInterrupt, cb)
|
|
|
|
w.mu.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func notifyInterrupt() {
|
|
|
|
w.mu.Lock()
|
|
|
|
for _, f := range w.onInterrupt {
|
2017-09-24 13:32:16 +02:00
|
|
|
f()
|
2017-07-10 17:32:42 +02:00
|
|
|
}
|
|
|
|
w.mu.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func tryStartInterruptNotifier() {
|
|
|
|
w.mu.Lock()
|
|
|
|
defer w.mu.Unlock()
|
|
|
|
if len(w.onInterrupt) > 0 {
|
|
|
|
// this can't be moved to the task interrupt's `Run` function
|
|
|
|
// because it will not catch more than one ctrl/cmd+c, so
|
|
|
|
// we do it here. These tasks are canceled already too.
|
|
|
|
go func() {
|
|
|
|
ch := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(ch,
|
|
|
|
// kill -SIGINT XXXX or Ctrl+c
|
|
|
|
os.Interrupt,
|
|
|
|
syscall.SIGINT, // register that too, it should be ok
|
|
|
|
// os.Kill is equivalent with the syscall.SIGKILL
|
|
|
|
os.Kill,
|
|
|
|
syscall.SIGKILL, // register that too, it should be ok
|
|
|
|
// kill -SIGTERM XXXX
|
|
|
|
syscall.SIGTERM,
|
|
|
|
)
|
|
|
|
select {
|
|
|
|
case <-ch:
|
|
|
|
notifyInterrupt()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|