Documentation
¶
Overview ¶
Package procidentity observes OS process birth identity for PID-reuse protection.
A PID alone is not durable identity: after exit the number may be reassigned. Callers that later signal or attribute a process must re-observe the birth token recorded at claim time and refuse on mismatch or when identity cannot be proven on the host platform.
Index ¶
Constants ¶
const TokenVersionV1 = 1
TokenVersionV1 is the versioned native birth-token schema.
Variables ¶
var ( // ErrIdentityLost means the live process no longer matches the bound birth // token (exit + PID reuse, or observation failure). ErrIdentityLost = errors.New("process birth identity no longer matches") // ErrNotBound means the target was closed or never opened. ErrNotBound = errors.New("process target is not bound") // ErrUnsupportedPlatform means Bind cannot authorize destructive recovery // (no instance-stable signaling primitive — e.g. Darwin stalled-recovery path). ErrUnsupportedPlatform = errors.New("platform does not support instance-stable destructive recovery") // ErrAlreadyGone means the bound instance was already dead before a signal // could be delivered (e.g. pidfd ESRCH). Not a successful signal delivery. ErrAlreadyGone = errors.New("process instance already gone before signal delivery") )
Functions ¶
func CheckDestructiveRecoverySupported ¶
func CheckDestructiveRecoverySupported() error
CheckDestructiveRecoverySupported reports whether this GOOS can perform instance-stable destructive recovery (Bind + signal). Darwin and other unsupported platforms refuse before any registry fence (D-R11-04).
func FileDevIno ¶
FileDevIno returns device and inode for path when available.
func FileIdentityRequired ¶
func FileIdentityRequired() bool
FileIdentityRequired reports whether reclaim receipts must include file IDs.
func Match ¶
Match reports whether observed is the same process instance as expected. Both sides must be proven; a missing birth token never matches. TokenVersion 1 compares native fields. Legacy expected (version 0) may match via start_ms for plan/heartbeat, but Bind refuses legacy for destructive recovery.
Types ¶
type Identity ¶
type Identity struct {
PID int
StartTimeUnixMS uint64 // display/legacy; non-authoritative when TokenVersion>=1
BootID string
TokenVersion int // 1 = native authority
StartTicks uint64 // Linux
StartSec int64 // Darwin
StartUsec int64 // Darwin
Filetime uint64 // Windows FILETIME 100ns
Proven bool
}
Identity is a platform-defined birth token for one process instance.
TokenVersion 1 uses platform-native fields as authority (Linux start ticks + boot ID; Darwin sec/usec; Windows FILETIME). StartTimeUnixMS remains a display/legacy convenience and is not sole authority for v1 Match.
func FromRecord ¶
FromRecord reconstructs the identity persisted on a job record.
type Liveness ¶
type Liveness int
Liveness is a four-way observation of a recorded process instance. All platforms share this contract (E-R7 / D-R7).
const ( // LiveMatching: live process matches the recorded birth identity. LiveMatching Liveness = iota // LiveMismatched: a live PID exists but birth identity does not match // (original instance is gone via reuse). This is identity-loss, not // death-side authority for pre-bind takeover (entarch E-R7-02). LiveMismatched // Gone: instance is proven dead (ESRCH, zombie/terminal, pidfd ESRCH, exit code). Gone // Indeterminate: observation failed (permission, unknown); never death. Indeterminate )
type Target ¶
type Target struct {
// contains filtered or unexported fields
}
Target is an identity-bound handle for signalling one process instance.
On Linux it prefers a pidfd (kernel-bound to the process). On other platforms it re-validates the birth token immediately before every signal so a recycled PID cannot be targeted. Neither form is a raw "signal this number" API.
func Bind ¶
Bind opens an identity-bound target for the expected process instance. It fails closed when identity cannot be proven or the live process does not match.
func (*Target) HardStopOnly ¶
HardStopOnly reports whether this platform's stop primitive is a hard stop (e.g. Windows TerminateProcess) with no portable graceful TERM for arbitrary processes. Callers must report ForcedKill / hard-stop semantics and must not invent a TERM→grace→KILL story.
func (*Target) SignalKill ¶
SignalKill delivers an uncatchable kill to the bound instance.
func (*Target) SignalTerm ¶
SignalTerm delivers a graceful termination request to the bound instance.
func (*Target) Terminated ¶
Terminated reports whether the bound process instance is gone.
func (*Target) WaitTerminated ¶
WaitTerminated polls until the bound instance is gone or the timeout elapses. timeout == 0 means already expired (immediate return, no wait). timeout < 0 uses the 30s default. Callers sharing a monotonic deadline must pass remain() which may be 0 at expiry (D-R11-03).