slimtoolkit/slim · critical · call.error
ptrace.App.collect.wpid
ptrace.App.collect.wpid
Error message
wpid is -1
What it means
In ptrace.App.collect, the waitpid-based collection loop receives wpid == -1, meaning waitpid failed to report any stopped tracee child. The code marks the app failed (AppFailed) and pushes this structured error onto errorCh. A TODO notes this branch may leave the sensor stuck, i.e. the wait loop exited without a valid child event.
Source
Thrown at pkg/monitor/ptrace/ptrace.go:738
app.StateCh <- AppFailed
app.collectorDoneCh <- 2
return
}
logger.Tracef("wait4 -> wpid=%v wstatus=%v (Exited=%v Signaled=%v Signal='%v' Stopped=%v StopSignalInfo=%s TrapCause=%s)",
wpid,
ws,
ws.Exited(),
ws.Signaled(),
ws.Signal(),
ws.Stopped(),
StopSignalInfo(ws.StopSignal()),
SigTrapCauseInfo(ws.TrapCause()))
if wpid == -1 {
logger.Error("wpid = -1")
app.StateCh <- AppFailed
app.errorCh <- errors.SE("ptrace.App.collect.wpid", "call.error", fmt.Errorf("wpid is -1"))
// TODO(ivan): Investigate if this code branch leads to sensor becoming stuck.
// Should we collectorDoneCh <- 42?
return
}
callSig = 0 // reset
terminated := false
eventStop := false
handleCall := false
eventCode := 0
statusCode := 0
switch {
case ws.Exited():
terminated = true
statusCode = ws.ExitStatus()
case ws.Signaled():
terminated = true
statusCode = int(ws.Signal())View on GitHub (pinned to 81940d17fa)
Solutions
- Check whether the child process died before collection started (correlate with app crash logs)
- Handle EINTR by retrying waitpid instead of treating it as fatal
- Ensure only the tracer thread waits on the child (avoid competing waitpid calls)
- If the sensor gets stuck, force cleanup via collectorDoneCh as the TODO suggests
Defensive patterns
Strategy: try-catch
Try / catch
go func() {
select {
case err := <-app.errorCh:
if se, ok := err.(*errors.Err); ok && se.Code == "ptrace.App.collect.wpid" {
log.Errorf("collector lost tracee: %v", se)
// perform cleanup so sensor does not get stuck
close(collectorDoneCh)
}
}
}() Prevention
- Ensure a single waitpid owner thread
- Handle EINTR by retrying waitpid
- Watch for the stuck-sensor TODO; add timeouts on collection
- Verify the child survives until collection begins
When it happens
Trigger: trace() -> collect(): waitpid returns -1 (child already reaped, no children, or interrupted syscall not retried) instead of a valid tracee pid.
Common situations: Child exited and was reaped by another goroutine/thread; EINTR from a signal handler not handled; all tracees already terminated by the time collect waits.
Related errors
- insufficient permissions
- one or more monitors failed: fanotify.error=%q, ptrace.error
- ptmon: target app startup failed: %q
- ptmon: unexpected target app state %q
- ptmon: target app failed with state %q
AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31).
Data as JSON: /api/errors/d99c887cddd2ccd0.
Report an issue: GitHub.