Documentation
¶
Overview ¶
Package proc provides platform-agnostic process management with safety guarantees.
It abstracts away OS-specific details for reliable process termination:
- Windows: Uses Job Objects to ensure child processes are killed when the parent exits.
- Linux: Uses Pdeathsig (SIGKILL) for the same guarantee.
Recommended Usage ¶
Use NewCmd to create a command with context-linked cancellation and then call Start to apply platform hygiene and launch the process:
cmd := proc.NewCmd(ctx, "worker", "--config", "prod.yaml")
cmd.Stdout = os.Stdout // configure before starting
if err := proc.Start(cmd); err != nil {
log.Fatal(err)
}
cmd.Wait()
Legacy Usage ¶
If you must construct the command yourself (e.g. to set SysProcAttr), use exec.CommandContext directly and pass to Start:
cmd := exec.CommandContext(ctx, "ping", "google.com") _ = proc.Start(cmd) cmd.Wait()
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var StrictMode bool
StrictMode if true, will cause Start to return an error on unsupported platforms instead of just logging a warning. Default is false.
Functions ¶
func NewCmd ¶ added in v0.2.0
NewCmd creates an *exec.Cmd pre-configured with context-linked cancellation (exec.CommandContext semantics). It is the recommended entry point when the caller holds a context, replacing the error-prone two-step pattern:
// before cmd := exec.CommandContext(ctx, name, args...) err := proc.Start(cmd) // after cmd := proc.NewCmd(ctx, name, args...) err := proc.Start(cmd)
NewCmd does NOT call Start. The caller must still call proc.Start(cmd) to apply platform hygiene attributes (Pdeathsig on Linux, Job Objects on Windows) and launch the process. This separation allows configuring Stdout, Stdin, Env, Dir, etc. before starting.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/aretw0/procio/proc"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
// NewCmd combines exec.CommandContext with automatic platform hygiene.
// It is the recommended entry point: no need to import os/exec directly.
cmd := proc.NewCmd(ctx, "sleep", "1")
if err := proc.Start(cmd); err != nil {
fmt.Println("Error starting process:", err)
return
}
// Wait for process to finish or context to be cancelled.
_ = cmd.Wait()
}
func Start ¶
Start starts the specified command but ensures that the child process is killed if the parent process (this process) dies.
On Linux, it uses SysProcAttr.Pdeathsig (SIGKILL). On Windows, it uses Job Objects (JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE).
On other platforms, it falls back to cmd.Start() and logs a warning, unless StrictMode is set to true, in which case it returns an error.
This is a safer alternative to cmd.Start() for long-running child processes.
Example ¶
package main
import (
"context"
"fmt"
"os/exec"
"time"
"github.com/aretw0/procio/proc"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
// Start a process. proc.Start wraps the standard exec.Cmd to provide
// platform-specific guarantees (Job Objects on Windows, Pdeathsig on Linux)
// that ensure child processes are terminated when the parent process exits.
cmd := exec.CommandContext(ctx, "sleep", "1")
// Start the process with hygiene guarantees.
if err := proc.Start(cmd); err != nil {
fmt.Println("Error starting process:", err)
return
}
// Wait for process to finish or context to be cancelled.
_ = cmd.Wait()
}
Types ¶
This section is empty.