dotnet/runtime · error

Problem reading from createdump child_read_pipe: %s (%d)\n

Error message

Problem reading from createdump child_read_pipe: %s (%d)\n

What it means

Emitted by the forked child in the CoreCLR PAL crash-dump path PROCLaunchCreateDump (process.cpp:1527). After fork the child closes the parent-side fds and blocks on read(child_read_pipe) waiting for the parent's single-byte prctl(PR_SET_PTRACER) signal; the read is retried only on EINTR. If bytesRead != 1 (read returned 0 = EOF or a hard error) the child prints this, closes child_write_pipe and exit(-1) BEFORE the g_createdumpCallback / execve branch is ever reached, so no dump is generated by either mechanism.

Source

Thrown at src/coreclr/pal/src/thread/process.cpp:1527

        }
        return false;
    }
    else if (childpid == 0)
    {
        int callbackResult = 0;

        close(parent_read_pipe);
        close(parent_write_pipe);

        // Wait for prctl(PR_SET_PTRACER, childpid) in parent
        char buffer;
        int bytesRead;
        while((bytesRead = read(child_read_pipe, &buffer, 1)) < 0 && errno == EINTR);
        close(child_read_pipe);

        if (bytesRead != 1)
        {
            fprintf(stderr, "Problem reading from createdump child_read_pipe: %s (%d)\n", strerror(errno), errno);
            close(child_write_pipe);
            exit(-1);
        }

        // Only dup the child's stderr if there is error buffer
        if (errorMessageBuffer != nullptr)
        {
            dup2(child_write_pipe, STDERR_FILENO);
        }
        if (g_createdumpCallback != nullptr)
        {
            // Remove the signal handlers inherited from the runtime process
            SEHCleanupSignals(true /* isChildProcess */);

            // Call the statically linked createdump code
            int argc = 0;
            while (argv[argc] != nullptr && argc < MAX_ARGV_ENTRIES)
            {

View on GitHub (pinned to 290d5ab72c)

Solutions

  1. Enable verbose diagnostics and reproduce: set DOTNET_CreateDumpDiagnostics=1 DOTNET_CreateDumpVerboseDiagnostics=1 to capture what the parent did before it stopped writing.
  2. Check for external kills during the crash: `dmesg -T | grep -i 'killed process'` (oom-killer) and container runtime OOM events; raise cgroup memory limits.
  3. Raise the open-files limit (ulimit -n) so the crash path has the fds it needs for the two pipes.
  4. If PR_SET_PTRACER setup is the culprit (hardened kernel/Yama ptrace_scope), set /proc/sys/kernel/yama/ptrace_scope to 0 or 1, or run as root, to let the parent complete the prctl step.
  5. Fall back to kernel core dumps: unset DOTNET_DbgEnableMiniDump and configure /proc/sys/kernel/core_pattern, removing the dependency on the in-process fork handshake.

Example fix

# before
$ DOTNET_DbgEnableMiniDump=1 ./app
# Problem reading from createdump child_read_pipe: Success (0)   # parent died (EOF)

# after: confirm/relieve the cause of the parent dying
$ dmesg -T | grep -i 'killed process'
$ ulimit -n 65536
$ DOTNET_DbgEnableMiniDump=1 DOTNET_CreateDumpVerboseDiagnostics=1 ./app
Defensive patterns

Strategy: validation

Validate before calling

# Validate that the parent can complete the prctl handshake on this host before enabling dumps.
cat /proc/sys/kernel/yama/ptrace_scope 2>/dev/null | grep -Eq '^[01]$' || echo "WARN: ptrace_scope may block PR_SET_PTRACER"
[ "$(ulimit -n)" -ge 1024 ] || ulimit -n 65536
# Ensure the process won't be OOM-killed during crash handling:
grep MemAvailable /proc/meminfo
DOTNET_DbgEnableMiniDump=1 DOTNET_CreateDumpVerboseDiagnostics=1 "$@"

Prevention

When it happens

Trigger: DOTNET_DbgEnableMiniDump=1 (or a runtime-triggered dump) on the full CoreCLR runtime causes a fork; the child is waiting on child_read_pipe but the parent never wrote the 'S' byte because it died, was killed, or crashed inside the prctl(PR_SET_PTRACER) block (lines 1571-1577) before reaching the write() at line 1580. The child's read then returns EOF.

Common situations: Parent process killed by the OOM killer or a container runtime between fork and the signal write; parent took a second, more fatal signal (e.g. SIGSEGV in the signal handler itself) during prctl setup; pipe fds exhausted/closed prematurely; running under a debugger or tracer that interferes with PR_SET_PTRACER and the parent aborted; very tight memory/fd limits on the crash path.

Related errors


AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06). Data as JSON: /api/errors/c0a4eee8788abf51. Report an issue: GitHub.