diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-01-11 17:46:04 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-01-11 17:46:04 +0900 |
| commit | 7ccc2fc5ece9c6236c02585ef4048fdc2b4a5b51 (patch) | |
| tree | 3e63ab8aeb380b256cc36c42c5ca4c1cac8de728 /internal/pkg/exec.go | |
| parent | 63e137856e47bb9cb472fc58ee6ea0b2e6c666b8 (diff) | |
internal/pkg: exec with specific timeout
This change also updates the documentation of NewExec.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/exec.go')
| -rw-r--r-- | internal/pkg/exec.go | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/internal/pkg/exec.go b/internal/pkg/exec.go index db0cf9f0..2ded00e9 100644 --- a/internal/pkg/exec.go +++ b/internal/pkg/exec.go @@ -42,6 +42,13 @@ func MustPath(pathname string, writable bool, a ...Artifact) ExecPath { return ExecPath{check.MustAbs(pathname), a, writable} } +const ( + // ExecTimeoutDefault replaces out of range [NewExec] timeout values. + ExecTimeoutDefault = 15 * time.Minute + // ExecTimeoutMax is the arbitrary upper bound of [NewExec] timeout. + ExecTimeoutMax = 48 * time.Hour +) + // An execArtifact is an [Artifact] that produces output by running a program // part of another [Artifact] in a [container] to produce its output. // @@ -59,6 +66,11 @@ type execArtifact struct { path *check.Absolute // Passed through to [container.Params]. args []string + + // Duration the initial process is allowed to run. The zero value is + // equivalent to execTimeoutDefault. This value is never encoded in Params + // because it cannot affect outcome. + timeout time.Duration } // execNetArtifact is like execArtifact but implements [KnownChecksum] and has @@ -88,10 +100,9 @@ func (a *execNetArtifact) Cure(f *FContext) error { return a.cure(f, true) } -// NewExec returns a new [Artifact] bounded by ctx, it cures all [Artifact] -// in paths at the specified maximum concurrent cures limit. Specified paths are -// bind mounted read-only in the specified order in the resulting container. -// A private instance of /proc and /dev is made available to the container. +// NewExec returns a new [Artifact] that executes the program path in a +// container with specified paths bind mounted read-only in order. A private +// instance of /proc and /dev is made available to the container. // // The working and temporary directories are both created and mounted writable // on [AbsWork] and [fhs.AbsTmp] respectively. If one or more paths target @@ -103,8 +114,14 @@ func (a *execNetArtifact) Cure(f *FContext) error { // // If checksum is non-nil, the resulting [Artifact] implements [KnownChecksum] // and its container runs in the host net namespace. +// +// The container is allowed to run for the specified duration before the initial +// process and all processes originating from it is terminated. A zero or +// negative timeout value is equivalent tp [ExecTimeoutDefault], a timeout value +// greater than [ExecTimeoutMax] is equivalent to [ExecTimeoutMax]. func NewExec( checksum *Checksum, + timeout time.Duration, dir *check.Absolute, env []string, @@ -113,7 +130,13 @@ func NewExec( paths ...ExecPath, ) Artifact { - a := execArtifact{paths, dir, env, path, args} + if timeout <= 0 { + timeout = ExecTimeoutDefault + } + if timeout > ExecTimeoutMax { + timeout = ExecTimeoutMax + } + a := execArtifact{paths, dir, env, path, args, timeout} if checksum == nil { return &a } @@ -197,7 +220,7 @@ func (a *execArtifact) cure(f *FContext, hostNet bool) (err error) { artifactCount += len(p.A) } - ctx, cancel := context.WithCancel(f.Unwrap()) + ctx, cancel := context.WithTimeout(f.Unwrap(), a.timeout) defer cancel() z := container.New(ctx, f.GetMessage()) |
