feat(executor/local): clock time limit
This commit is contained in:
parent
58c6d5607f
commit
98cf2c812f
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
@ -16,44 +17,13 @@ import (
|
|||
|
||||
type Local struct{}
|
||||
|
||||
func (e *Local) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) {
|
||||
var results []stage.ExecutorResult
|
||||
|
||||
for _, cmd := range cmds {
|
||||
execCmd := exec.Command(cmd.Args[0], cmd.Args[1:]...) // #nosec G204
|
||||
|
||||
env := os.Environ()
|
||||
if len(cmd.Env) > 0 {
|
||||
env = append(env, cmd.Env...)
|
||||
}
|
||||
execCmd.Env = env
|
||||
|
||||
if cmd.Stdin != nil {
|
||||
if cmd.Stdin.Content != nil {
|
||||
execCmd.Stdin = strings.NewReader(*cmd.Stdin.Content)
|
||||
} else if cmd.Stdin.Src != nil {
|
||||
file, err := os.Open(*cmd.Stdin.Src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open stdin file: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
execCmd.Stdin = file
|
||||
}
|
||||
}
|
||||
var stdoutBuffer, stderrBuffer bytes.Buffer
|
||||
execCmd.Stdout = &stdoutBuffer
|
||||
execCmd.Stderr = &stderrBuffer
|
||||
|
||||
startTime := time.Now()
|
||||
err := execCmd.Start()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to start command: %v", err)
|
||||
}
|
||||
|
||||
err = execCmd.Wait()
|
||||
endTime := time.Now()
|
||||
runTime := endTime.Sub(startTime)
|
||||
processState := execCmd.ProcessState
|
||||
func generateResult(
|
||||
err error,
|
||||
processState *os.ProcessState,
|
||||
runTime time.Duration,
|
||||
cmd stage.Cmd,
|
||||
stdoutBuffer, stderrBuffer bytes.Buffer,
|
||||
) stage.ExecutorResult {
|
||||
result := stage.ExecutorResult{
|
||||
Status: stage.Status(envexec.StatusAccepted),
|
||||
ExitStatus: processState.ExitCode(),
|
||||
|
@ -111,7 +81,94 @@ func (e *Local) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) {
|
|||
result.Error = err.Error()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (e *Local) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) {
|
||||
var results []stage.ExecutorResult
|
||||
|
||||
for _, cmd := range cmds {
|
||||
execCmd := exec.Command(cmd.Args[0], cmd.Args[1:]...) // #nosec G204
|
||||
if cmd.CPULimit > 0 && cmd.ClockLimit <= 0 {
|
||||
cmd.ClockLimit = cmd.CPULimit * 2
|
||||
}
|
||||
env := os.Environ()
|
||||
if len(cmd.Env) > 0 {
|
||||
env = append(env, cmd.Env...)
|
||||
}
|
||||
execCmd.Env = env
|
||||
|
||||
if cmd.Stdin != nil {
|
||||
if cmd.Stdin.Content != nil {
|
||||
execCmd.Stdin = strings.NewReader(*cmd.Stdin.Content)
|
||||
} else if cmd.Stdin.Src != nil {
|
||||
file, err := os.Open(*cmd.Stdin.Src)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open stdin file: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
execCmd.Stdin = file
|
||||
}
|
||||
}
|
||||
var stdoutBuffer, stderrBuffer bytes.Buffer
|
||||
execCmd.Stdout = &stdoutBuffer
|
||||
execCmd.Stderr = &stderrBuffer
|
||||
|
||||
startTime := time.Now()
|
||||
err := execCmd.Start()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to start command: %v", err)
|
||||
}
|
||||
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- execCmd.Wait()
|
||||
}()
|
||||
|
||||
if cmd.ClockLimit > 0 {
|
||||
var duration time.Duration
|
||||
if cmd.ClockLimit > uint64(math.MaxInt64) {
|
||||
duration = time.Duration(math.MaxInt64)
|
||||
} else {
|
||||
duration = time.Duration(cmd.ClockLimit) * time.Nanosecond // #nosec G115
|
||||
}
|
||||
select {
|
||||
case err := <-done:
|
||||
endTime := time.Now()
|
||||
runTime := endTime.Sub(startTime)
|
||||
result := generateResult(
|
||||
err,
|
||||
execCmd.ProcessState,
|
||||
runTime,
|
||||
cmd,
|
||||
stdoutBuffer,
|
||||
stderrBuffer,
|
||||
)
|
||||
results = append(results, result)
|
||||
case <-time.After(duration):
|
||||
_ = execCmd.Process.Kill()
|
||||
result := stage.ExecutorResult{
|
||||
Status: stage.Status(envexec.StatusTimeLimitExceeded),
|
||||
Error: "",
|
||||
Files: map[string]string{},
|
||||
FileIDs: map[string]string{},
|
||||
}
|
||||
results = append(results, result)
|
||||
}
|
||||
} else {
|
||||
err := <-done
|
||||
endTime := time.Now()
|
||||
runTime := endTime.Sub(startTime)
|
||||
result := generateResult(
|
||||
err,
|
||||
execCmd.ProcessState,
|
||||
runTime,
|
||||
cmd,
|
||||
stdoutBuffer,
|
||||
stderrBuffer,
|
||||
)
|
||||
results = append(results, result)
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
|
|
Loading…
Reference in New Issue
Block a user