{"record":{"id":"263bb6578a404769","repo":"dotnet/runtime","slug":"problem-waiting-for-createdump-waitpid-failed-r","errorCode":null,"errorMessage":"Problem waiting for createdump: waitpid() FAILED result %d wstatus %08x errno %s (%d)\\n","messagePattern":"Problem waiting for createdump: waitpid\\(\\) FAILED result (.+?) wstatus %08x errno (.+?) \\((.+?)\\)\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp","lineNumber":336,"sourceCode":"            int count = 0;\n            while ((count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0)\n            {\n                bytesRead += count;\n            }\n            errorMessageBuffer[bytesRead] = 0;\n            if (bytesRead > 0)\n            {\n                fputs(errorMessageBuffer, stderr);\n            }\n        }\n        close(parent_read_pipe);\n\n        // Parent waits until the child process is done\n        int wstatus = 0;\n        int result = waitpid(childpid, &wstatus, 0);\n        if (result != childpid)\n        {\n            fprintf(stderr, \"Problem waiting for createdump: waitpid() FAILED result %d wstatus %08x errno %s (%d)\\n\",\n                result, wstatus, strerror(errno), errno);\n            return false;\n        }\n        else\n        {\n#ifdef _DEBUG\n            fprintf(stderr, \"waitpid() returned successfully (wstatus %08x) WEXITSTATUS %x WTERMSIG %x\\n\", wstatus, WEXITSTATUS(wstatus), WTERMSIG(wstatus));\n#endif\n            return !WIFEXITED(wstatus) || WEXITSTATUS(wstatus) == 0;\n        }\n    }\n    return true;\n}\n\n#endif // !defined(HOST_MACCATALYST) && !defined(HOST_IOS) && !defined(HOST_TVOS)\n\n// Helper function to prevent compiler from optimizing away a variable\n#if defined(__llvm__)","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/dotnet/runtime/blob/290d5ab72cc1102813fbc0406fb186ceadabc340/src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp#L318-L354","documentation":"Emitted by the NativeAOT parent in CreateCrashDump (PalCreateDump.cpp:336) when waitpid(childpid, &wstatus, 0) returns a value other than childpid. The PAL does not loop on EINTR here, so a single interrupted waitpid surfaces as a hard failure (return false). The dominant cause is ECHILD: the createdump child was already reaped by something else, so the runtime's waitpid finds no child to wait for.","triggerScenarios":"DOTNET_DbgEnableMiniDump=1 crash path reaches the parent's waitpid but another agent reaped the forked createdump child first, or waitpid was interrupted by an unblocked signal (EINTR) and not retried. result != childpid triggers the fprintf and returns false even though createdump may have run.","commonSituations":"A service supervisor or PID-1 init (tini/dumb-init, systemd, Kubernetes pause) configured to reap all children stole the child exit status; a SIGCHLD handler in a native dependency called wait/waitpid globally; signal delivery (EINTR) during a heavily signal-loaded crash; on some libc/glibc versions a race with thread library helper threads.","solutions":["If a container init/PID-1 reaper is stealing the child, disable child reaping for this process or run the app as PID 1 without a reaper (or use a reaper that only reaps truly orphaned children).","Run createdump indirectly through the OS core pattern instead: unset DOTNET_DbgEnableMiniDump and configure /proc/sys/kernel/core_pattern to invoke createdump so the kernel owns the wait.","Inspect whether any embedded native library installs a global SIGCHLD handler and have it not reap unknown children.","Reproduce with DOTNET_CreateDumpVerboseDiagnostics=1 to confirm whether createdump actually completed (the waitpid failure may be a false negative).","If unavoidable in the deployment, accept that dumps may be unreliable here and capture coredumps at the OS level as the primary mechanism."],"exampleFix":"# before: a PID-1 reaper steals the createdump child\n$ docker run --init myapp   # tini reaps children -> waitpid() FAILED ECHILD\n\n# after: let the runtime own its child, or use the kernel core pattern\n$ docker run myapp                     # no --init reaper\n$ echo '|/usr/share/dotnet/createdump %p %e' > /proc/sys/kernel/core_pattern\n$ ulimit -c unlimited && ./app","handlingStrategy":"validation","validationCode":"# Detect a child-reaping PID-1 / SIGCHLD handler that would break waitpid.\nps -o pid,comm -p 1 | grep -Eqi 'tini|dumb-init|init|systemd' && echo \"WARN: PID 1 may reap createdump child\"\n# If reaping is present, plan to use the kernel core pattern instead:\n[ -w /proc/sys/kernel/core_pattern ] && echo '|/usr/share/dotnet/createdump %p %e' > /proc/sys/kernel/core_pattern || echo \"core_pattern not writable; avoid DOTNET_DbgEnableMiniDump here\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid container init systems that reap all children (docker --init, tini) when relying on DOTNET_DbgEnableMiniDump.","Use /proc/sys/kernel/core_pattern to drive createdump from the kernel so the runtime never waitpids.","Audit loaded native libraries for global SIGCHLD handlers before enabling in-process dumps.","Verify dumps were actually written (ls *.dmp) rather than trusting exit status, since a waitpid false-negative can mask a successful createdump."],"tags":["dotnet","nativeaot","createdump","crash-dump","waitpid","linux","diagnostics"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}