procio

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Feb 26, 2026 License: AGPL-3.0 Imports: 1 Imported by: 1

README

procio

Go Report Card Go Reference License Release

procio is a lightweight, standalone set of composable primitives for safe process lifecycle and interactive I/O in Go.

It provides three core primitives:

  • proc: Leak-free process management (ensures child processes die when parent dies).
  • termio: Interruptible terminal I/O (handling interrupts and safe terminal handles).
  • scan: Robust input scanning with protection against "Fake EOF" signals on Windows.

Installation

go get github.com/aretw0/procio

Usage

Starting a Process Safely
import "github.com/aretw0/procio/proc"

cmd := proc.NewCmd(ctx, "long-running-worker")
// Uses Pdeathsig (Linux) or Job Objects (Windows) to enforce cleanup
err := cmd.Start()
Reading Input Robustly
import "github.com/aretw0/procio/scan"

scanner := scan.NewScanner(os.Stdin)
scanner.Start(ctx) // Handles transient interrupts
Enabling TTY Cancellation

For interactive CLIs that need Ctrl+C cancellation support:

import (
    "context"
    "github.com/aretw0/procio/scan"
)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

scanner := scan.NewScanner(os.Stdin,
    scan.WithInterruptible(), // Enables context cancellation via Ctrl+C
    scan.WithLineHandler(func(line string) {
        fmt.Println("Got:", line)
    }),
)

scanner.Start(ctx) // Returns when context is cancelled or EOF
Chained Cancels

proc.NewCmd integrates naturally with derived contexts, so cancellation hierarchies work as expected:

// appCtx controls the whole application lifetime.
appCtx, appCancel := context.WithCancel(context.Background())
defer appCancel()

// subCtx adds a deadline for a specific subprocess.
subCtx, subCancel := context.WithTimeout(appCtx, 10*time.Second)
defer subCancel()

cmd := proc.NewCmd(subCtx, "worker")
if err := cmd.Start(); err != nil {
    log.Fatal(err)
}
cmd.Wait()
// worker is terminated when subCtx expires OR when appCtx is cancelled —
// whichever comes first. Platform hygiene (Job Objects / Pdeathsig) is
// still applied regardless of which signal arrives first.
Advanced Features

procio provides primitives for advanced process control:

Pseudo-Terminals (PTY)

Wrap interactive applications:

import "github.com/aretw0/procio/pty"

cmd := exec.CommandContext(ctx, "vim")
p, err := pty.StartPTY(cmd)
// Forward p.Controller to/from host Stdin/Stdout
Streaming Telemetry

Monitor processes in real-time (Linux & Windows):

ch, err := proc.Monitor(ctx, cmd, time.Second)
for m := range ch {
    fmt.Printf("CPU: %.1f%% Mem: %d KB\n", m.CPUPercent, m.MemRSS/1024)
}

Observability

procio is opinionated about specific mechanisms but unopinionated about logging/metrics. You can inject your own observer:

import "github.com/aretw0/procio"

procio.SetObserver(myObserver)

See docs/RECIPES.md for a complete log/slog adapter example.

License

This project is licensed under the terms of the AGPL-3.0.

Documentation

Overview

Package procio is the root package for robust process I/O and signaling primitives.

It provides a platform-agnostic way to handle process execution and terminal input with safety guarantees (like leak-free process termination using Job Objects on Windows and Pdeathsig on Linux).

Subpackages

  • proc: Process management and lifecycle guarantees.
  • scan: Context-aware parsing of input streams (Scanner).
  • termio: Terminal I/O utilities and interruptible readers.

Observability

procio does not depend on any logging library. Instead, it exposes an Observer interface that you can implement to bridge logs and metrics to your preferred system.

Index

Examples

Constants

This section is empty.

Variables

View Source
var Version string

Functions

func SetObserver

func SetObserver(o Observer)

SetObserver configures the global observer for process events.

Example
package main

import (
	"fmt"

	"github.com/aretw0/procio"
)

// MyObserver implements procio.Observer
type MyObserver struct{}

func (o *MyObserver) OnProcessStarted(pid int)         { fmt.Printf("Started PID: %d\n", pid) }
func (o *MyObserver) OnProcessFailed(err error)        { fmt.Printf("Failed: %v\n", err) }
func (o *MyObserver) OnIOError(op string, err error)   { fmt.Printf("IO Error (%s): %v\n", op, err) }
func (o *MyObserver) OnScanError(err error)            { fmt.Printf("Scan Error: %v\n", err) }
func (o *MyObserver) LogDebug(msg string, args ...any) {}
func (o *MyObserver) LogWarn(msg string, args ...any)  { fmt.Printf("%s\n", msg) }
func (o *MyObserver) LogError(msg string, args ...any) {}

func main() {
	// Set a custom observer to receive lifecycle and IO hooks
	procio.SetObserver(&MyObserver{})

	// Emitting a log to demonstrate (internally used by procio packages)
	obs := procio.GetObserver()
	obs.LogWarn("Observer configured successfully")

	// Reset to default (noop) when done
	procio.SetObserver(nil)

}
Output:

Observer configured successfully

Types

type Observer

type Observer interface {
	OnProcessStarted(pid int)
	OnProcessFailed(err error)
	OnIOError(op string, err error)
	OnScanError(err error)
	LogDebug(msg string, args ...any)
	LogWarn(msg string, args ...any)
	LogError(msg string, args ...any)
}

Observer allows external packages to plug in observability (logs, metrics) without coupling this module to specific implementations.

func GetObserver

func GetObserver() Observer

GetObserver returns the current global observer. Useful for sub-packages to access the shared observer.

Directories

Path Synopsis
examples
basic command
composition command
interruptible command
lifecycle_bridge command
Package main demonstrates how to integrate procio with lifecycle.
Package main demonstrates how to integrate procio with lifecycle.
observer command
pty command
Package proc provides platform-agnostic process management with safety guarantees.
Package proc provides platform-agnostic process management with safety guarantees.
Package pty provides pseudo-terminal (PTY) primitives for running interactive applications within child processes.
Package pty provides pseudo-terminal (PTY) primitives for running interactive applications within child processes.
Package scan provides a robust, context-aware command and line scanner.
Package scan provides a robust, context-aware command and line scanner.
Package termio provides interruptible I/O primitives and terminal handling.
Package termio provides interruptible I/O primitives and terminal handling.

Jump to

Keyboard shortcuts

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