Browse Source

command: fix Windows build

Add a per GOOS implementation to send signals to PIDs
since syscall.Kill does not exist on Windows.

It will always send a SIGKILL on Windows since there
seems to be no POSIX compatible notion.

Fixes build on Windows.
pull/637/head
Emil Hessman 10 years ago
parent
commit
8cdbde20bd
  1. 20
      command/lock.go
  2. 12
      command/util_unix.go
  3. 19
      command/util_windows.go

20
command/lock.go

@ -27,7 +27,7 @@ const (
)
// LockCommand is a Command implementation that is used to setup
// a "lock" which manages lock acquasition and invokes a sub-process
// a "lock" which manages lock acquisition and invokes a sub-process
type LockCommand struct {
ShutdownCh <-chan struct{}
Ui cli.Ui
@ -47,6 +47,8 @@ Usage: consul lock [options] prefix child...
the child process will be sent a SIGTERM signal and given time to
gracefully exit. After the grace period expires the process will
be hard terminated.
On Windows agents, the process is always hard terminated, even on
the first attempt.
When -n=1, only a single lock holder or leader exists providing
mutual exclusion. Setting a higher value switches to a semaphore
@ -286,6 +288,8 @@ func (c *LockCommand) startChild(script string, doneCh chan struct{}) error {
// killChild is used to forcefully kill the child, first using SIGTERM
// to allow for a graceful cleanup and then using SIGKILL for a hard
// termination.
// On Windows, the child is always hard terminated with SIGKILL, even
// on the first attempt.
func (c *LockCommand) killChild(childDone chan struct{}) error {
// Get the child process
c.childLock.Lock()
@ -300,11 +304,11 @@ func (c *LockCommand) killChild(childDone chan struct{}) error {
return nil
}
// Attempt a SIGTERM first
// Attempt termination first
if c.verbose {
c.Ui.Info(fmt.Sprintf("Sending SIGTERM to child pid %d", child.Pid))
c.Ui.Info(fmt.Sprintf("Terminating child pid %d", child.Pid))
}
if err := syscall.Kill(child.Pid, syscall.SIGTERM); err != nil {
if err := signalPid(child.Pid, syscall.SIGTERM); err != nil {
return fmt.Errorf("Failed to terminate %d: %v", child.Pid, err)
}
@ -312,7 +316,7 @@ func (c *LockCommand) killChild(childDone chan struct{}) error {
select {
case <-childDone:
if c.verbose {
c.Ui.Info("Child exited after SIGTERM")
c.Ui.Info("Child terminated")
}
return nil
case <-time.After(lockKillGracePeriod):
@ -322,11 +326,11 @@ func (c *LockCommand) killChild(childDone chan struct{}) error {
}
}
// Send a final SIGKILL first
// Send a final SIGKILL
if c.verbose {
c.Ui.Info(fmt.Sprintf("Sending SIGKILL to child pid %d", child.Pid))
c.Ui.Info(fmt.Sprintf("Killing child pid %d", child.Pid))
}
if err := syscall.Kill(child.Pid, syscall.SIGKILL); err != nil {
if err := signalPid(child.Pid, syscall.SIGKILL); err != nil {
return fmt.Errorf("Failed to kill %d: %v", child.Pid, err)
}
return nil

12
command/util_unix.go

@ -0,0 +1,12 @@
// +build !windows
package command
import (
"syscall"
)
// signalPid sends a sig signal to the process with process id pid.
func signalPid(pid int, sig syscall.Signal) error {
return syscall.Kill(pid, sig)
}

19
command/util_windows.go

@ -0,0 +1,19 @@
// +build windows
package command
import (
"os"
"syscall"
)
// signalPid sends a sig signal to the process with process id pid.
// Interrupts et al is not implemented on Windows. Always send a SIGKILL.
func signalPid(pid int, sig syscall.Signal) error {
p, err := os.FindProcess(pid)
if err != nil {
return err
}
_ = sig
return p.Signal(syscall.SIGKILL)
}
Loading…
Cancel
Save