allow controlling the stop signal in exec/raw_exec

This commit is contained in:
Chelsea Holland Komlo 2017-11-21 17:27:52 -05:00
parent 2a69339ef8
commit 80de7d5ebd
3 changed files with 35 additions and 3 deletions

View File

@ -30,6 +30,7 @@ IMPROVEMENTS:
* driver/docker: Adds support for `ulimit` and `sysctl` options [GH-3568]
* driver/docker: Adds support for StopTimeout (set to the same value as
kill_timeout [GH-3601]
* driver/exec: allow controlling the stop signal in exec/raw_exec [GH-1755]
* driver/rkt: Add support for passing through user [GH-3612]
* driver/qemu: Support graceful shutdowns on unix platforms [GH-3411]
* template: Updated to consul template 0.19.4 [GH-3543]

View File

@ -31,8 +31,9 @@ type ExecDriver struct {
}
type ExecDriverConfig struct {
Command string `mapstructure:"command"`
Args []string `mapstructure:"args"`
Command string `mapstructure:"command"`
Args []string `mapstructure:"args"`
KillSignal string `mapstructure:"kill_signal"`
}
// execHandle is returned from Start/Open as a handle to the PID
@ -67,6 +68,9 @@ func (d *ExecDriver) Validate(config map[string]interface{}) error {
"args": {
Type: fields.TypeArray,
},
"kill_signal": {
Type: fields.TypeString,
},
},
}
@ -132,6 +136,7 @@ func (d *ExecDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse
execCmd := &executor.ExecCommand{
Cmd: command,
Args: driverConfig.Args,
KillSignal: driverConfig.KillSignal,
FSIsolation: true,
ResourceLimits: true,
User: getExecutorUser(task),

View File

@ -98,6 +98,8 @@ type ExecCommand struct {
// Args is the args of the command that the user wants to run.
Args []string
KillSignal string
// FSIsolation determines whether the command would be run in a chroot.
FSIsolation bool
@ -481,6 +483,21 @@ func (e *UniversalExecutor) Exit() error {
return merr.ErrorOrNil()
}
// Look to see if the user has specified a kill command. If non has been
// specified, default to SIGQUIT.
func getMatchingSyscall(sys string) syscall.Signal {
switch sys {
case "SIGINT":
return syscall.SIGINT
case "SIGUSR1":
return syscall.SIGUSR1
case "SIGUSR2":
return syscall.SIGUSR2
default:
return syscall.SIGQUIT
}
}
// Shutdown sends an interrupt signal to the user process
func (e *UniversalExecutor) ShutDown() error {
if e.cmd.Process == nil {
@ -496,9 +513,18 @@ func (e *UniversalExecutor) ShutDown() error {
}
return nil
}
if err = proc.Signal(os.Interrupt); err != nil && err.Error() != finishedErr {
var killErr error
if e.command.KillSignal != "" {
sys := getMatchingSyscall(e.command.KillSignal)
killErr = syscall.Kill(e.cmd.Process.Pid, sys)
} else {
killErr = proc.Signal(os.Interrupt)
}
if killErr != nil && killErr.Error() != finishedErr {
return fmt.Errorf("executor.shutdown error: %v", err)
}
return nil
}