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 optionUserServiceDefault = false
optionSessionCreate = "SessionCreate" optionSessionCreate = "SessionCreate"
optionSessionCreateDefault = false optionSessionCreateDefault = false
optionRunWait = "RunWait"
optionReloadSignal = "ReloadSignal"
) )
// Config provides the setup for a Service. The Name field is required. // Config provides the setup for a Service. The Name field is required.
@@ -106,6 +109,9 @@ type Config struct {
// - RunAtLoad bool (false) // - RunAtLoad bool (false)
// - UserService bool (false) - Install as a current user service. // - UserService bool (false) - Install as a current user service.
// - SessionCreate bool (false) - Create a full user session. // - 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 Option KeyValue
} }
@@ -143,7 +149,7 @@ func New(i Interface, c *Config) (Service, error) {
// more details. // more details.
type KeyValue map[string]interface{} 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. // 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 { func (kv KeyValue) bool(name string, defaultValue bool) bool {
if v, found := kv[name]; found { if v, found := kv[name]; found {
@@ -154,7 +160,7 @@ func (kv KeyValue) bool(name string, defaultValue bool) bool {
return defaultValue 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. // 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 { func (kv KeyValue) int(name string, defaultValue int) int {
if v, found := kv[name]; found { if v, found := kv[name]; found {
@@ -165,7 +171,7 @@ func (kv KeyValue) int(name string, defaultValue int) int {
return defaultValue 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. // 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 { func (kv KeyValue) string(name string, defaultValue string) string {
if v, found := kv[name]; found { if v, found := kv[name]; found {
@@ -176,7 +182,7 @@ func (kv KeyValue) string(name string, defaultValue string) string {
return defaultValue 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. // 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 { func (kv KeyValue) float64(name string, defaultValue float64) float64 {
if v, found := kv[name]; found { if v, found := kv[name]; found {
@@ -187,6 +193,17 @@ func (kv KeyValue) float64(name string, defaultValue float64) float64 {
return defaultValue 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. // Platform returns a description of the system service.
func Platform() string { func Platform() string {
if system == nil { if system == nil {
+5 -5
View File
@@ -196,11 +196,11 @@ func (s *darwinLaunchdService) Run() error {
return err return err
} }
var sigChan = make(chan os.Signal, 3) s.Option.funcSingle(optionRunWait, func() {
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt) signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
<-sigChan })()
return s.i.Stop(s) return s.i.Stop(s)
} }
+8 -5
View File
@@ -80,9 +80,11 @@ func (s *systemd) Install() error {
var to = &struct { var to = &struct {
*Config *Config
Path string Path string
ReloadSignal string
}{ }{
s.Config, s.Config,
path, path,
s.Option.string(optionReloadSignal, ""),
} }
err = s.template().Execute(f, to) err = s.template().Execute(f, to)
@@ -128,11 +130,11 @@ func (s *systemd) Run() (err error) {
return err return err
} }
sigChan := make(chan os.Signal, 3) s.Option.funcSingle(optionRunWait, func() {
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt) signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
<-sigChan })()
return s.i.Stop(s) return s.i.Stop(s)
} }
@@ -160,6 +162,7 @@ ExecStart={{.Path|cmdEscape}}{{range .Arguments}} {{.|cmd}}{{end}}
{{if .ChRoot}}RootDirectory={{.ChRoot|cmd}}{{end}} {{if .ChRoot}}RootDirectory={{.ChRoot|cmd}}{{end}}
{{if .WorkingDirectory}}WorkingDirectory={{.WorkingDirectory|cmd}}{{end}} {{if .WorkingDirectory}}WorkingDirectory={{.WorkingDirectory|cmd}}{{end}}
{{if .UserName}}User={{.UserName}}{{end}} {{if .UserName}}User={{.UserName}}{{end}}
{{if .ReloadSignal}}ExecReload=/bin/kill -{{.ReloadSignal}} "$MAINPID"{{end}}
Restart=always Restart=always
RestartSec=120 RestartSec=120
+5 -5
View File
@@ -127,11 +127,11 @@ func (s *sysv) Run() (err error) {
return err return err
} }
sigChan := make(chan os.Signal, 3) s.Option.funcSingle(optionRunWait, func() {
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt) signal.Notify(sigChan, syscall.SIGTERM, os.Interrupt)
<-sigChan
<-sigChan })()
return s.i.Stop(s) return s.i.Stop(s)
} }
+5 -5
View File
@@ -117,11 +117,11 @@ func (s *upstart) Run() (err error) {
return err return err
} }
sigChan := make(chan os.Signal, 3) s.Option.funcSingle(optionRunWait, func() {
var sigChan = make(chan os.Signal, 3)
signal.Notify(sigChan, os.Interrupt, os.Kill) signal.Notify(sigChan, os.Interrupt, os.Kill)
<-sigChan
<-sigChan })()
return s.i.Stop(s) return s.i.Stop(s)
} }