safeexec

package
v1.46.0 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: AGPL-3.0 Imports: 8 Imported by: 0

Documentation

Overview

Package safeexec provides a thin wrapper around os/exec that pre-sets WaitDelay on every command. This eliminates the zombie process accumulation hazard that occurs when exec.CommandContext is used directly: if the context expires and SIGKILL is sent to the process, cmd.Wait() can block indefinitely when a grandchild (e.g. git credential helper, shell wrapper) holds the stdout/stderr pipes open. WaitDelay forces Wait() to return and close pipes after 2 seconds regardless.

Usage: replace exec.CommandContext(ctx, ...) with safeexec.CommandContext(ctx, ...). The returned *exec.Cmd is identical to exec.CommandContext's result except that WaitDelay is already set.

The norawexec lint rule enforces that application code uses this package instead of calling exec.Command or exec.CommandContext directly.

Package safeexec provides thin wrappers around os/exec that pre-set WaitDelay on every command. This eliminates the zombie process accumulation hazard that occurs when exec.CommandContext is used directly.

Index

Constants

View Source
const DefaultWaitDelay = 2 * time.Second

DefaultWaitDelay is the time to wait after SIGKILL before forcibly closing pipes. Set to 2 seconds: generous enough not to truncate output on slow machines, tight enough to bound zombie lifetime to a few seconds.

Variables

This section is empty.

Functions

func CommandContext

func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd

CommandContext returns an exec.Cmd backed by ctx with WaitDelay pre-set to DefaultWaitDelay. Use it wherever exec.CommandContext would be used.

func CommandContextPG

func CommandContextPG(ctx context.Context, name string, arg ...string) *exec.Cmd

CommandContextPG returns an exec.Cmd with WaitDelay pre-set AND Setpgid: true, so cmd.Cancel (overridden below) can SIGTERM the whole process group instead of just the direct child, catching grandchildren the child spawns.

IMPORTANT: Do NOT use CommandContextPG for processes needing a controlling terminal (e.g. "tmux attach-session" via pty.Start()) — Setpgid without a matching Setsid can trigger SIGTTIN/SIGTTOU. Use CommandContext for those.

func EnsurePdeathsig added in v1.37.0

func EnsurePdeathsig(cmd *exec.Cmd)

EnsurePdeathsig arranges for cmd's child process to be SIGKILLed by the kernel if this process dies for any reason, including SIGKILL — a signal Go code cannot intercept to run its own cleanup (ctx cancellation and deferred kill/Wait calls never execute in that case).

Use this for long-running children (e.g. tmux control-mode attach) whose lifecycle is otherwise "managed by the caller via ctx" — that management only works if the caller gets to run its own shutdown code, which isn't guaranteed for short-lived processes (e.g. one `stapler-squad --mcp` process per Claude Code session) that their own parent may SIGKILL.

Preserves any SysProcAttr fields already set (e.g. Setpgid) by mutating in place rather than replacing the struct — call after other SysProcAttr setup but before cmd.Start()/pty.Start(cmd).

Types

This section is empty.

Jump to

Keyboard shortcuts

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