Skip to content

Instantly share code, notes, and snippets.

@arikfr
Last active December 17, 2015 06:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arikfr/5567783 to your computer and use it in GitHub Desktop.
Save arikfr/5567783 to your computer and use it in GitHub Desktop.
Safe shutdown in Go.
package main
import (
"log"
"shutdown"
)
func main() {
ch := shutdown.Add("test")
ch2 := shutdown.Add("test2")
go func() {
for {
select {
case <-ch2:
log.Printf("Received the signal")
shutdown.Done("test2")
case <-ch:
log.Printf("Received the signal")
shutdown.Done("test")
}
}
}()
shutdown.Shutdown(1000)
}
package shutdown
import (
"log"
"time"
)
var waitingList map[string]chan bool
var waitCh chan string
func init() {
waitingList = make(map[string]chan bool)
waitCh = make(chan string)
}
func Add(name string) chan bool {
if ch, ok := waitingList[name]; ok {
return ch
}
log.Printf("Shutdown: registering <%s>.", name)
waitingList[name] = make(chan bool)
return waitingList[name]
}
func Done(name string) {
log.Printf("Shutdown: <%s> finished.", name)
go func() {
waitCh <- name
}()
}
func Shutdown(timeout int) {
for name, ch := range waitingList {
log.Printf("Notifying <%s>.", name)
ch <- true
}
var timeoutCh <-chan time.Time
if timeout > 0 {
timeoutCh = time.After(time.Duration(timeout) * time.Millisecond)
} else {
timeoutCh = make(chan time.Time)
}
for {
select {
case name := <-waitCh:
delete(waitingList, name)
if len(waitingList) == 0 {
log.Printf("All done.")
return
}
case <-timeoutCh:
log.Printf("Timeout expired... unfinished processes:")
for name, _ := range waitingList {
log.Printf(name)
}
return
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment