mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 18:51:03 +01:00
15feaf0237
Former-commit-id: dced7d472edabbab4f80c76051f13261928a8dea
77 lines
2.0 KiB
Go
77 lines
2.0 KiB
Go
package host
|
|
|
|
import (
|
|
"os"
|
|
"os/signal"
|
|
"sync"
|
|
"syscall"
|
|
)
|
|
|
|
// RegisterOnInterrupt registers a global function to call when CTRL+C/CMD+C pressed or a unix kill command received.
|
|
func RegisterOnInterrupt(cb func()) {
|
|
Interrupt.Register(cb)
|
|
}
|
|
|
|
// Interrupt watches the os.Signals for interruption signals
|
|
// and fires the callbacks when those happens.
|
|
// A call of its `FireNow` manually will fire and reset the registered interrupt handlers.
|
|
var Interrupt = new(interruptListener)
|
|
|
|
type interruptListener struct {
|
|
mu sync.Mutex
|
|
once sync.Once
|
|
// onInterrupt contains a list of the functions that should be called when CTRL+C/CMD+C or
|
|
// a unix kill command received.
|
|
onInterrupt []func()
|
|
}
|
|
|
|
// Register registers a global function to call when CTRL+C/CMD+C pressed or a unix kill command received.
|
|
func (i *interruptListener) Register(cb func()) {
|
|
if cb == nil {
|
|
return
|
|
}
|
|
|
|
i.listenOnce()
|
|
i.mu.Lock()
|
|
i.onInterrupt = append(i.onInterrupt, cb)
|
|
i.mu.Unlock()
|
|
}
|
|
|
|
// FireNow can be called more than one times from a Consumer in order to
|
|
// execute all interrupt handlers manually.
|
|
func (i *interruptListener) FireNow() {
|
|
i.mu.Lock()
|
|
for _, f := range i.onInterrupt {
|
|
f()
|
|
}
|
|
i.onInterrupt = i.onInterrupt[0:0]
|
|
i.mu.Unlock()
|
|
}
|
|
|
|
// listenOnce fires a goroutine which calls the interrupt handlers when CTRL+C/CMD+C and e.t.c.
|
|
// If `FireNow` called before then it does nothing when interrupt signal received,
|
|
// so it's safe to be used side by side with `FireNow`.
|
|
//
|
|
// Btw this `listenOnce` is called automatically on first register, it's useless for outsiders.
|
|
func (i *interruptListener) listenOnce() {
|
|
i.once.Do(func() { go i.notifyAndFire() })
|
|
}
|
|
|
|
func (i *interruptListener) notifyAndFire() {
|
|
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:
|
|
i.FireNow()
|
|
}
|
|
}
|