mirror of
https://github.com/kontera-technologies/go-supervisor
synced 2025-09-27 03:25:53 +08:00
196 lines
6.3 KiB
Go
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
|
|
}
|