diff --git a/README.md b/README.md index b57b589..f536090 100755 --- a/README.md +++ b/README.md @@ -245,17 +245,20 @@ nginx: command: "docker stop nginx_test" timeout_seconds: 10 # default 10 signal: 15 # default 15, but only if the 'command' is not defined or empty + parent_only: no # default no. If yes, only signal the running process instead of its whole process group ``` -`shutdown` is optional and can be omitted. The default behavior in this case: `SIGTERM` is issued to the running process. +`shutdown` is optional and can be omitted. The default behavior in this case: `SIGTERM` is issued to the process group of the running process. -In case only `shutdown.signal` is defined `[1..31] ` the running process will be terminated with its value. +In case only `shutdown.signal` is defined `[1..31] ` the running process group will be terminated with its value. + +If `shutdown.parent_only` is yes, the signal is only sent to the running process and not to the whole process group. In case the `shutdown.command` is defined: 1. The `shutdown.command` is executed with all the Environment Variables of the primary process 2. Wait for `shutdown.timeout_seconds` for its completion (if not defined wait for 10 seconds) -3. In case of timeout, the process will receive the `SIGKILL` signal +3. In case of timeout, the process group will receive the `SIGKILL` signal (irrespective of the `shutdown.parent_only` option). ##### Background (detached) Processes diff --git a/src/app/process.go b/src/app/process.go index f595e9c..bc91139 100644 --- a/src/app/process.go +++ b/src/app/process.go @@ -248,7 +248,8 @@ func (p *Process) shutDown() error { if isStringDefined(p.procConf.ShutDownParams.ShutDownCommand) { return p.doConfiguredStop(p.procConf.ShutDownParams) } - return p.stop(p.procConf.ShutDownParams.Signal) + + return p.stop(p.procConf.ShutDownParams.Signal, p.procConf.ShutDownParams.ParentOnly) } func (p *Process) doConfiguredStop(params types.ShutDownParams) error { @@ -267,7 +268,7 @@ func (p *Process) doConfiguredStop(params types.ShutDownParams) error { if err := cmd.Run(); err != nil { // the process termination timedout and it will be killed log.Error().Msgf("terminating %s with timeout %d failed - %s", p.getName(), timeout, err.Error()) - return p.stop(int(syscall.SIGKILL)) + return p.stop(int(syscall.SIGKILL), false) } return nil } diff --git a/src/app/process_unix.go b/src/app/process_unix.go index 3eb46b6..de7717f 100644 --- a/src/app/process_unix.go +++ b/src/app/process_unix.go @@ -3,6 +3,7 @@ package app import ( + "github.com/rs/zerolog/log" "syscall" ) @@ -11,17 +12,30 @@ const ( max_sig = 31 ) -func (p *Process) stop(sig int) error { +func (p *Process) stop(sig int, parentOnly bool) error { if p.command == nil { return nil } if sig < min_sig || sig > max_sig { sig = int(syscall.SIGTERM) } + + log. + Debug(). + Int("pid", p.command.Process.Pid). + Int("signal", sig). + Bool("parentOnly", parentOnly). + Msg("Stop Unix process.") + + if parentOnly { + return syscall.Kill(p.command.Process.Pid, syscall.Signal(sig)) + } + pgid, err := syscall.Getpgid(p.command.Process.Pid) if err == nil { return syscall.Kill(-pgid, syscall.Signal(sig)) } + return err } diff --git a/src/app/process_windows.go b/src/app/process_windows.go index 448dd8b..2420fd1 100644 --- a/src/app/process_windows.go +++ b/src/app/process_windows.go @@ -5,7 +5,7 @@ import ( "strconv" ) -func (p *Process) stop(sig int) error { +func (p *Process) stop(sig int, _parentOnly bool) error { //p.command.Process.Kill() kill := exec.Command("TASKKILL", "/T", "/F", "/PID", strconv.Itoa(p.command.Process.Pid)) return kill.Run() diff --git a/src/types/process.go b/src/types/process.go index 8dc53cc..0935484 100644 --- a/src/types/process.go +++ b/src/types/process.go @@ -91,6 +91,7 @@ type ShutDownParams struct { ShutDownCommand string `yaml:"command,omitempty"` ShutDownTimeout int `yaml:"timeout_seconds,omitempty"` Signal int `yaml:"signal,omitempty"` + ParentOnly bool `yaml:"parent_only,omitempty"` } const (