Files
go-supervisor_lib/process-options.go
motiisr 47fd9c75b7 support run timeout (#7)
* support run timeout

* fix tests
2022-01-23 11:25:06 +02:00

196 lines
6.3 KiB
Go

package supervisor
import (
"io"
"os"
"syscall"
"time"
)
type ProcessOptions struct {
// If Name contains no path separators, Command uses LookPath to
// resolve Name to a complete path if possible. Otherwise it uses Name
// directly as Path.
Name string
// The returned Cmd's Args field is constructed from the command name
// followed by the elements of arg, so arg should not include the
// command name itself. For example, Command("echo", "hello").
// Args[0] is always name, not the possibly resolved Path.
Args []string
// Env specifies the environment of the process.
// Each entry is of the form "key=value".
// If Env is nil, the new process uses the current process's
// environment.
// If Env contains duplicate environment keys, only the last
// value in the slice for each duplicate key is used.
Env []string
// When InheritEnv is true, os.Environ() will be prepended to Env.
InheritEnv bool
// Dir specifies the working directory of the command.
// If Dir is the empty string, Run runs the command in the
// calling process's current directory.
Dir string
// ExtraFiles specifies additional open files to be inherited by the
// new process. It does not include standard input, standard output, or
// standard error. If non-nil, entry i becomes file descriptor 3+i.
//
// ExtraFiles is not supported on Windows.
ExtraFiles []*os.File
// SysProcAttr holds optional, operating system-specific attributes.
// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
SysProcAttr *syscall.SysProcAttr
In chan []byte
Out chan *interface{}
Err chan *interface{}
EventNotifier chan Event
Id string
// Debug - when this flag is set to true, events will be logged to the default go logger.
Debug bool
OutputParser func(fromR io.Reader, bufferSize int) ProduceFn
ErrorParser func(fromR io.Reader, bufferSize int) ProduceFn
// MaxSpawns is the maximum number of times that a process can be spawned
// Set to -1, for an unlimited amount of times.
// Will use defaultMaxSpawns when set to 0.
MaxSpawns int
// MaxSpawnAttempts is the maximum number of spawns attempts for a process.
// Set to -1, for an unlimited amount of attempts.
// Will use defaultMaxSpawnAttempts when set to 0.
MaxSpawnAttempts int
// MaxSpawnBackOff is the maximum duration that we will wait between spawn attempts.
// Will use defaultMaxSpawnBackOff when set to 0.
MaxSpawnBackOff time.Duration
// MaxRespawnBackOff is the maximum duration that we will wait between respawn attempts.
// Will use defaultMaxRespawnBackOff when set to 0.
MaxRespawnBackOff time.Duration
// MaxInterruptAttempts is the maximum number of times that we will try to interrupt the process when closed, before
// terminating and/or killing it.
// Set to -1, to never send the interrupt signal.
// Will use defaultMaxInterruptAttempts when set to 0.
MaxInterruptAttempts int
// MaxTerminateAttempts is the maximum number of times that we will try to terminate the process when closed, before
// killing it.
// Set to -1, to never send the terminate signal.
// Will use defaultMaxTerminateAttempts when set to 0.
MaxTerminateAttempts int
// NotifyEventTimeout is the amount of time that the process will BLOCK while trying to send an event.
NotifyEventTimeout time.Duration
// ParserBufferSize is the size of the buffer to be used by the OutputParser and ErrorParser.
// Will use defaultParserBufferSize when set to 0.
ParserBufferSize int
// IdleTimeout is the duration that the process can remain idle (no output) before we terminate the process.
// Set to -1, for an unlimited idle timeout (not recommended)
// Will use defaultIdleTimeout when set to 0.
IdleTimeout time.Duration
// TerminationGraceTimeout is the duration of time that the supervisor will wait after sending interrupt/terminate
// signals, before checking if the process is still alive.
// Will use defaultTerminationGraceTimeout when set to 0.
TerminationGraceTimeout time.Duration
// EventTimeFormat is the time format used when events are marshaled to string.
// Will use defaultEventTimeFormat when set to "".
EventTimeFormat string
// RunTimeout is the duration that the process can run before we terminate the process.
// Set to <= 0, for an unlimited run timeout
// Will use defaultRunTimeout when set to 0.
RunTimeout time.Duration
}
// init initializes the opts structure with default and required options.
func initProcessOptions(opts ProcessOptions) *ProcessOptions {
if opts.SysProcAttr == nil {
opts.SysProcAttr = &syscall.SysProcAttr{}
} else {
opts.SysProcAttr = deepCloneSysProcAttr(*opts.SysProcAttr)
}
// Start a new process group for the spawned process.
opts.SysProcAttr.Setpgid = true
if opts.InheritEnv {
opts.Env = append(os.Environ(), opts.Env...)
}
if opts.MaxSpawns == 0 {
opts.MaxSpawns = defaultMaxSpawns
}
if opts.MaxSpawnAttempts == 0 {
opts.MaxSpawnAttempts = defaultMaxSpawnAttempts
}
if opts.MaxSpawnBackOff == 0 {
opts.MaxSpawnBackOff = defaultMaxSpawnBackOff
}
if opts.MaxRespawnBackOff == 0 {
opts.MaxRespawnBackOff = defaultMaxRespawnBackOff
}
if opts.MaxInterruptAttempts == 0 {
opts.MaxInterruptAttempts = defaultMaxInterruptAttempts
}
if opts.MaxTerminateAttempts == 0 {
opts.MaxTerminateAttempts = defaultMaxTerminateAttempts
}
if opts.NotifyEventTimeout == 0 {
opts.NotifyEventTimeout = defaultNotifyEventTimeout
}
if opts.ParserBufferSize == 0 {
opts.ParserBufferSize = defaultParserBufferSize
}
if opts.IdleTimeout == 0 {
opts.IdleTimeout = defaultIdleTimeout
}
if opts.IdleTimeout < 0 {
opts.IdleTimeout = time.Duration(maxDuration)
}
if opts.TerminationGraceTimeout == 0 {
opts.TerminationGraceTimeout = defaultTerminationGraceTimeout
}
if opts.EventTimeFormat == "" {
opts.EventTimeFormat = defaultEventTimeFormat
}
if opts.RunTimeout <= 0 {
opts.RunTimeout = defaultRunTimeout
}
if opts.In == nil {
opts.In = make(chan []byte)
}
if opts.Out == nil {
opts.Out = make(chan *interface{})
}
if opts.Err == nil {
opts.Err = make(chan *interface{})
}
return &opts
}
// deepCloneSysProcAttr is a helper function that deep-copies the syscall.SysProcAttr struct and returns a reference to the
// new struct.
func deepCloneSysProcAttr(x syscall.SysProcAttr) *syscall.SysProcAttr {
if x.Credential != nil {
y := *x.Credential
x.Credential = &y
}
return &x
}