Files
codapi/engine/exec.go
2023-11-25 04:02:45 +05:00

55 lines
1.4 KiB
Go

package engine
import (
"context"
"io"
"os/exec"
"strings"
"time"
"github.com/nalgeon/codapi/execy"
"github.com/nalgeon/codapi/logx"
)
// A Program is an executable program.
type Program struct {
timeout time.Duration
nOutput int64
}
// NewProgram creates a new program.
func NewProgram(timeoutSec int, nOutput int64) *Program {
return &Program{
timeout: time.Duration(timeoutSec) * time.Second,
nOutput: nOutput,
}
}
// Run starts the program and waits for it to complete (or timeout).
func (p *Program) Run(id, name string, arg ...string) (stdout string, stderr string, err error) {
return p.RunStdin(nil, id, name, arg...)
}
// RunStdin starts the program with data from stdin
// and waits for it to complete (or timeout).
func (p *Program) RunStdin(stdin io.Reader, id, name string, arg ...string) (stdout string, stderr string, err error) {
ctx, cancel := context.WithTimeout(context.Background(), p.timeout)
defer cancel()
var cmdout, cmderr strings.Builder
cmd := exec.CommandContext(ctx, name, arg...)
cmd.Cancel = func() error {
err := cmd.Process.Kill()
logx.Debug("%s: execution timeout, killed process=%d, err=%v", id, cmd.Process.Pid, err)
return err
}
cmd.Stdin = stdin
cmd.Stdout = LimitWriter(&cmdout, p.nOutput)
cmd.Stderr = LimitWriter(&cmderr, p.nOutput)
err = execy.Run(cmd)
stdout = cmdout.String()
stderr = cmderr.String()
return
}