Help us shape the future of Go! Take the 2026 Go Developer Survey

shim

package
v1.9.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 26, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package shim is the child side of out-of-process execution.

A sandboxed process re-execs the worker's own binary, which calls Main. Main builds a bare job.Registry and a credential-free artifact.Service over a local directory, reads a request, runs the handler, and writes a result. It never constructs an engine, a store, or a DI container, so the process that parses an untrusted file holds no database credential and no object-store client.

Index

Constants

View Source
const (
	// EnvRequestFD names the environment variable that overrides which
	// file descriptor Main reads the exec.Request from. Unset, Main reads
	// fd 3 — the parent's convention for the first descriptor past
	// stdin/stdout/stderr.
	EnvRequestFD = "DISPATCH_EXEC_REQUEST_FD"

	// EnvResultFD names the environment variable that overrides which
	// file descriptor Main writes the exec.Result to. Unset, Main writes
	// fd 4.
	EnvResultFD = "DISPATCH_EXEC_RESULT_FD"

	// ArgName is the argv[1] marker a parent sets when it re-execs its own
	// binary into the shim, distinguishing that invocation from an
	// ordinary run of the worker. argv[0] is still the binary path itself,
	// same as any other invocation — subprocess.Executor.Run builds the
	// child's argv as [binary, ArgName, ...WithArgs], so this is the first
	// argument after the binary, not the zeroth.
	ArgName = "dispatch-exec"

	// EnvRlimitAS, EnvRlimitNoFile, EnvRlimitNProc, EnvRlimitCore, and
	// EnvRlimitFSize name the environment variables the parent uses to
	// pass POSIX resource limits into the child. Go cannot set a child's
	// rlimits through os/exec's SysProcAttr, so the parent (see buildEnv
	// in exec/subprocess) passes the desired values here, and Main
	// applies them itself via syscall.Setrlimit — see applyRlimits —
	// before running anything. Each is unset when the parent has no
	// value to send, except EnvRlimitCore, which the parent always sends
	// as "0".
	EnvRlimitAS     = "DISPATCH_RLIMIT_AS"
	EnvRlimitNoFile = "DISPATCH_RLIMIT_NOFILE"
	EnvRlimitNProc  = "DISPATCH_RLIMIT_NPROC"
	EnvRlimitCore   = "DISPATCH_RLIMIT_CORE"
	EnvRlimitFSize  = "DISPATCH_RLIMIT_FSIZE"

	// EnvRlimitStrict names the environment variable the parent sets
	// (see subprocess.WithStrictRlimits) to ask Main to fail the launch
	// outright when an rlimit it was actually asked to apply fails for a
	// reason other than "this platform does not support that limit at
	// all" — see applyRlimits for the distinction. Set to any non-empty
	// value to enable; unset (the default) keeps every rlimit failure
	// non-fatal.
	EnvRlimitStrict = "DISPATCH_RLIMIT_STRICT"
)

Variables

This section is empty.

Functions

func Main

func Main(defs ...job.Registrable)

Main is the sandboxed child's entrypoint. It builds a bare job.Registry from defs and a credential-free artifact.Service over a local directory, reads one exec.Request from its request descriptor, runs the matching handler, and writes one exec.Result to its result descriptor.

Main never returns: it calls os.Exit. A handler returning an error is exit 0, since that is a business outcome the Result frame already carries as StatusHandlerError. A nonzero exit means the shim itself failed the attempt before or instead of running the handler — a request that failed to decode, or one whose fingerprint or handler name did not resolve — which is what lets the parent distinguish those cases from a clean run without having to inspect the frame first: the exit code corroborates what the Result already says.

func Run

func Run(ctx context.Context, in io.Reader, out io.Writer, defs []job.Registrable) error

Run is the testable core of the shim: it reads one exec.Request from in, runs the matching handler out of defs, and writes one exec.Result to out. Splitting it from Main is what lets tests drive it with in-memory buffers instead of real file descriptors.

Run returns a non-nil error only when it could not produce a Result frame at all — the request failed to decode, or was malformed enough that there is no attempt to report on. Every failure that happens once a well-formed request is in hand — an unknown handler, a fingerprint mismatch, the handler itself erroring — is reported by writing a Result frame and returning nil, because the frame is the report, not the error: the parent reads Status, not the shim's exit code, to learn what happened.

Run discards the Result it produces, keeping its signature exactly what callers (and the brief's test) expect. mainExitCode needs that Result to derive an exit code, which Run's error alone cannot give it — see run.

Types

type LocalFS

type LocalFS struct {
	// contains filtered or unexported fields
}

LocalFS is a directory-backed artifact.Backend. It stores every object as a plain file under root, so the process holding it needs no object store credential — only a directory it can read and write.

LocalFS is built for the exec/shim boundary: a sandboxed child process writes its outputs here, and the parent collects them from the filesystem once the child exits, without the child ever holding a network client for the real object store.

func NewLocalFS

func NewLocalFS(root string) *LocalFS

NewLocalFS returns a Backend that stores objects as files under root. The caller is responsible for root existing and being writable; LocalFS creates subdirectories under it as needed but never creates root itself.

func (*LocalFS) Create

func (fs *LocalFS) Create(_ context.Context, bucket, key string) (artifact.Writer, error)

Create begins writing a new object. The bytes are not visible until Commit.

func (*LocalFS) Delete

func (fs *LocalFS) Delete(_ context.Context, ref artifact.Ref) error

Delete removes the object. Deleting a missing object is not an error.

func (*LocalFS) Name

func (fs *LocalFS) Name() string

Name identifies this backend.

func (*LocalFS) Open

func (fs *LocalFS) Open(_ context.Context, ref artifact.Ref) (io.ReadCloser, error)

Open returns a reader over the object's bytes.

func (*LocalFS) Stat

Stat reports the object's size without reading it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL