Make the signal handling concurrent safe.

This commit is contained in:
Dave Collins 2013-10-03 09:28:18 -05:00
parent 35c95f0a36
commit c1b327c06a

View file

@ -12,9 +12,31 @@ import (
// interruptChannel is used to receive SIGINT (Ctrl+C) signals.
var interruptChannel chan os.Signal
// interruptCallbacks is a list of callbacks to invoke when a SIGINT (Ctrl+C) is
// received.
var interruptCallbacks []func()
// addHandlerChannel is used to add an interrupt handler to the list of handlers
// to be invoked on SIGINT (Ctrl+C) signals.
var addHandlerChannel = make(chan func())
// mainInterruptHandler listens for SIGINT (Ctrl+C) signals on the
// interruptChannel and invokes the registered interruptCallbacks accordingly.
// It also listens for callback registration. It must be run as a goroutine.
func mainInterruptHandler() {
// interruptCallbacks is a list of callbacks to invoke when a
// SIGINT (Ctrl+C) is received.
var interruptCallbacks []func()
for {
select {
case <-interruptChannel:
for _, callback := range interruptCallbacks {
callback()
}
os.Exit(0)
case handler := <-addHandlerChannel:
interruptCallbacks = append(interruptCallbacks, handler)
}
}
}
// addInterruptHandler adds a handler to call when a SIGINT (Ctrl+C) is
// received.
@ -24,13 +46,8 @@ func addInterruptHandler(handler func()) {
if interruptChannel == nil {
interruptChannel = make(chan os.Signal, 1)
signal.Notify(interruptChannel, os.Interrupt)
go func() {
<-interruptChannel
for _, callback := range interruptCallbacks {
callback()
}
os.Exit(0)
}()
go mainInterruptHandler()
}
interruptCallbacks = append(interruptCallbacks, handler)
addHandlerChannel <- handler
}