grim/convey

Bump the version for release
v0.11.1
2017-10-21, Gary Kramlich
00923ff4e245
Bump the version for release
/*
* Convey
* Copyright 2016-2017 Gary Kramlich <grim@reaperworld.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cleanup
import (
"os"
"os/signal"
"sync"
"syscall"
"bitbucket.org/rw_grim/convey/logging"
"bitbucket.org/rw_grim/convey/util"
)
type (
// List is a list of things that should happen in case the
// program receives a signal. This should be things like making
// sure temp files are deleted, volumes are destroyed, etc.
List struct {
funcs map[string]Func
mutex sync.RWMutex
}
// Func is a function to run on exit (it should be quick).
Func func()
)
// NewList will create a new List that will run all registered
// functions on SIGINT or SIGTERM.
func NewList() *List {
var (
ch = make(chan os.Signal, 1)
list = &List{funcs: map[string]Func{}}
adapter = logging.NewAdapter("main")
)
go func() {
<-ch
adapter.Fatal("Received signal, cleaning up")
list.run()
os.Exit(1)
}()
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
return list
}
// Add will register a function to be invoked on system exit
// unless the returned function is called. The given function
// is wrapped in the return function, so it can be used in its
// place. This function MUST be called in order to deregister
// it on exit if it cannot be called idempotently. The order of
// functions invoked on exit is not guaranteed to be stable.
func (c *List) Add(fn Func) func() {
c.mutex.Lock()
defer c.mutex.Unlock()
name := util.ShortID()
c.funcs[name] = fn
return func() { c.fire(name) }
}
func (c *List) fire(name string) {
c.mutex.Lock()
c.funcs[name]()
delete(c.funcs, name)
c.mutex.Unlock()
}
func (c *List) run() {
c.mutex.Lock()
defer c.mutex.Unlock()
for _, fn := range c.funcs {
fn()
}
}