service: update API to allow for programs that install their own signal handlers.

This commit is contained in:
Daniel Theophanes
2016-02-05 09:48:50 -08:00
parent 2954cfdd7b
commit 5f98fcd9ec
5 changed files with 44 additions and 24 deletions
+21 -4
View File
@@ -78,6 +78,9 @@ const (
optionUserServiceDefault = false
optionSessionCreate = "SessionCreate"
optionSessionCreateDefault = false
optionRunWait = "RunWait"
optionReloadSignal = "ReloadSignal"
)
// Config provides the setup for a Service. The Name field is required.
@@ -106,6 +109,9 @@ type Config struct {
// - RunAtLoad bool (false)
// - UserService bool (false) - Install as a current user service.
// - SessionCreate bool (false) - Create a full user session.
// * POSIX
// - RunWait func() (wait for SIGNAL) - Do not install signal but wait for this function to return.
// - ReloadSignal string () [USR1, ...] - Signal to send on reaload.
Option KeyValue
}
@@ -143,7 +149,7 @@ func New(i Interface, c *Config) (Service, error) {
// more details.
type KeyValue map[string]interface{}
// Bool returns the value of the given name, assuming the value is a boolean.
// bool returns the value of the given name, assuming the value is a boolean.
// If the value isn't found or is not of the type, the defaultValue is returned.
func (kv KeyValue) bool(name string, defaultValue bool) bool {
if v, found := kv[name]; found {
@@ -154,7 +160,7 @@ func (kv KeyValue) bool(name string, defaultValue bool) bool {
return defaultValue
}
// Int returns the value of the given name, assuming the value is an int.
// int returns the value of the given name, assuming the value is an int.
// If the value isn't found or is not of the type, the defaultValue is returned.
func (kv KeyValue) int(name string, defaultValue int) int {
if v, found := kv[name]; found {
@@ -165,7 +171,7 @@ func (kv KeyValue) int(name string, defaultValue int) int {
return defaultValue
}
// Int returns the value of the given name, assuming the value is a string.
// string returns the value of the given name, assuming the value is a string.
// If the value isn't found or is not of the type, the defaultValue is returned.
func (kv KeyValue) string(name string, defaultValue string) string {
if v, found := kv[name]; found {
@@ -176,7 +182,7 @@ func (kv KeyValue) string(name string, defaultValue string) string {
return defaultValue
}
// Int returns the value of the given name, assuming the value is a float64.
// float64 returns the value of the given name, assuming the value is a float64.
// If the value isn't found or is not of the type, the defaultValue is returned.
func (kv KeyValue) float64(name string, defaultValue float64) float64 {
if v, found := kv[name]; found {
@@ -187,6 +193,17 @@ func (kv KeyValue) float64(name string, defaultValue float64) float64 {
return defaultValue
}
// funcSingle returns the value of the given name, assuming the value is a float64.
// If the value isn't found or is not of the type, the defaultValue is returned.
func (kv KeyValue) funcSingle(name string, defaultValue func()) func() {
if v, found := kv[name]; found {
if castValue, is := v.(func()); is {
return castValue
}
}
return defaultValue
}
// Platform returns a description of the system service.
func Platform() string {
if system == nil {
+5 -5
View File
@@ -196,11 +196,11 @@ func (s *darwinLaunchdService) Run() error {
return err
}
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
s.Option.funcSingle(optionRunWait, func() {
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
})()
return s.i.Stop(s)
}
+8 -5
View File
@@ -80,9 +80,11 @@ func (s *systemd) Install() error {
var to = &struct {
*Config
Path string
ReloadSignal string
}{
s.Config,
path,
s.Option.string(optionReloadSignal, ""),
}
err = s.template().Execute(f, to)
@@ -128,11 +130,11 @@ func (s *systemd) Run() (err error) {
return err
}
sigChan := make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
s.Option.funcSingle(optionRunWait, func() {
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
})()
return s.i.Stop(s)
}
@@ -160,6 +162,7 @@ ExecStart={{.Path|cmdEscape}}{{range .Arguments}} {{.|cmd}}{{end}}
{{if .ChRoot}}RootDirectory={{.ChRoot|cmd}}{{end}}
{{if .WorkingDirectory}}WorkingDirectory={{.WorkingDirectory|cmd}}{{end}}
{{if .UserName}}User={{.UserName}}{{end}}
{{if .ReloadSignal}}ExecReload=/bin/kill -{{.ReloadSignal}} "$MAINPID"{{end}}
Restart=always
RestartSec=120
+5 -5
View File
@@ -127,11 +127,11 @@ func (s *sysv) Run() (err error) {
return err
}
sigChan := make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
s.Option.funcSingle(optionRunWait, func() {
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
})()
return s.i.Stop(s)
}
+5 -5
View File
@@ -117,11 +117,11 @@ func (s *upstart) Run() (err error) {
return err
}
sigChan := make(chan os.Signal, 3)
signal.Notify(sigChan, os.Interrupt, os.Kill)
<-sigChan
s.Option.funcSingle(optionRunWait, func() {
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, os.Interrupt, os.Kill)
<-sigChan
})()
return s.i.Stop(s)
}