etcd-agent: tidy cleanup before SIGKILL

https://github.com/golang/go/blob/master/src/os/exec_posix.go#L18 shows that
cmd.Process.Kill calls syscall.SIGKILL to the command. But
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_01.html explains
'If you send a SIGKILL to a process, you remove any chance for the process to
do a tidy cleanup and shutdown, which might have unfortunate consequences.'
This sends SIGTERM, SIGINT syscalls to the PID so that the process could
have more time to clean up the resources.

Related to https://github.com/coreos/etcd/issues/4517.
This commit is contained in:
Gyu-Ho Lee 2016-02-16 11:03:12 -08:00
parent 30e4d7d6aa
commit 56e3ab0943

View File

@ -21,6 +21,7 @@ import (
"os"
"os/exec"
"path"
"syscall"
"time"
"github.com/coreos/etcd/pkg/netutil"
@ -80,20 +81,39 @@ func (a *Agent) stop() error {
if a.state != stateStarted {
return nil
}
err := a.cmd.Process.Kill()
if err != nil {
return err
}
_, err = a.cmd.Process.Wait()
if err != nil {
return err
err := sigtermAndWait(a.cmd)
if err != nil {
return err
}
a.state = stateStopped
return nil
}
func sigtermAndWait(cmd *exec.Cmd) error {
err := cmd.Process.Signal(syscall.SIGTERM)
if err != nil {
return err
}
errc := make(chan error)
go func() {
_, err := cmd.Process.Wait()
errc <- err
close(errc)
}()
select {
case <-time.After(5 * time.Second):
cmd.Process.Kill()
case err := <-errc:
return err
}
err = <-errc
return err
}
// restart restarts the stopped etcd process.
func (a *Agent) restart() error {
a.cmd = exec.Command(a.cmd.Path, a.cmd.Args[1:]...)