{"record":{"id":"d99c887cddd2ccd0","repo":"slimtoolkit/slim","slug":"ptrace-app-collect-wpid","errorCode":"ptrace.App.collect.wpid","errorMessage":"wpid is -1","messagePattern":"wpid is -1","errorType":"error_code","errorClass":"call.error","httpStatus":null,"severity":"critical","filePath":"pkg/monitor/ptrace/ptrace.go","lineNumber":738,"sourceCode":"\t\t\tapp.StateCh <- AppFailed\n\t\t\tapp.collectorDoneCh <- 2\n\t\t\treturn\n\t\t}\n\n\t\tlogger.Tracef(\"wait4 -> wpid=%v wstatus=%v (Exited=%v Signaled=%v Signal='%v' Stopped=%v StopSignalInfo=%s TrapCause=%s)\",\n\t\t\twpid,\n\t\t\tws,\n\t\t\tws.Exited(),\n\t\t\tws.Signaled(),\n\t\t\tws.Signal(),\n\t\t\tws.Stopped(),\n\t\t\tStopSignalInfo(ws.StopSignal()),\n\t\t\tSigTrapCauseInfo(ws.TrapCause()))\n\n\t\tif wpid == -1 {\n\t\t\tlogger.Error(\"wpid = -1\")\n\t\t\tapp.StateCh <- AppFailed\n\t\t\tapp.errorCh <- errors.SE(\"ptrace.App.collect.wpid\", \"call.error\", fmt.Errorf(\"wpid is -1\"))\n\t\t\t// TODO(ivan): Investigate if this code branch leads to sensor becoming stuck.\n\t\t\t//             Should we collectorDoneCh <- 42?\n\t\t\treturn\n\t\t}\n\n\t\tcallSig = 0 // reset\n\t\tterminated := false\n\t\teventStop := false\n\t\thandleCall := false\n\t\teventCode := 0\n\t\tstatusCode := 0\n\t\tswitch {\n\t\tcase ws.Exited():\n\t\t\tterminated = true\n\t\t\tstatusCode = ws.ExitStatus()\n\t\tcase ws.Signaled():\n\t\t\tterminated = true\n\t\t\tstatusCode = int(ws.Signal())","sourceCodeStart":720,"sourceCodeEnd":756,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/monitor/ptrace/ptrace.go#L720-L756","documentation":"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.","triggerScenarios":"trace() -> collect(): waitpid returns -1 (child already reaped, no children, or interrupted syscall not retried) instead of a valid tracee pid.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"go func() {\n    select {\n    case err := <-app.errorCh:\n        if se, ok := err.(*errors.Err); ok && se.Code == \"ptrace.App.collect.wpid\" {\n            log.Errorf(\"collector lost tracee: %v\", se)\n            // perform cleanup so sensor does not get stuck\n            close(collectorDoneCh)\n        }\n    }\n}()","preventionTips":["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"],"tags":["ptrace","waitpid","sensor-stuck"],"backgroundTag":"waitpid-failed","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}