dotnet/runtime · error

Problem writing to createdump parent_write_pipe: %s (%d)\n

Error message

Problem writing to createdump parent_write_pipe: %s (%d)\n

What it means

Emitted from the NativeAOT parent process in CreateCrashDump (PalCreateDump.cpp:304). After fork, the parent runs prctl(PR_SET_PTRACER, childpid) then writes a single 'S' byte through parent_write_pipe to release the child from its blocking read(); the write() is retried only on EINTR. If the final byte count is not 1 the parent prints this message, clears the error buffer, closes parent_read_pipe and returns false, so no dump is produced. The near-universal cause is a broken pipe: the child has already exited and closed its read end, so write() returns -1 with EPIPE.

Source

Thrown at src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp:304

#if HAVE_PRCTL_H && HAVE_PR_SET_PTRACER
        // Gives the child process permission to use /proc/<pid>/mem and ptrace
        if (prctl(PR_SET_PTRACER, childpid, 0, 0, 0) == -1)
        {
            // Ignore any error because on some CentOS and OpenSUSE distros, it isn't
            // supported but createdump works just fine.
#ifdef _DEBUG
            fprintf(stderr, "CreateCrashDump: prctl() FAILED %s (%d)\n", strerror(errno), errno);
#endif
        }
#endif // HAVE_PRCTL_H && HAVE_PR_SET_PTRACER
        // Signal child that prctl(PR_SET_PTRACER, childpid) is done
        int bytesWritten;
        while((bytesWritten = write(parent_write_pipe, "S", 1)) < 0 && errno == EINTR);
        close(parent_write_pipe);

        if (bytesWritten != 1)
        {
            fprintf(stderr, "Problem writing to createdump parent_write_pipe: %s (%d)\n", strerror(errno), errno);
            close(parent_read_pipe);
            if (errorMessageBuffer != nullptr)
            {
                errorMessageBuffer[0] = 0;
            }
            return false;
        }

        // Read createdump's stderr messages (if any)
        if (errorMessageBuffer != nullptr)
        {
            // Read createdump's stderr
            int bytesRead = 0;
            int count = 0;
            while ((count = read(parent_read_pipe, errorMessageBuffer + bytesRead, cbErrorMessageBuffer - bytesRead)) > 0)
            {
                bytesRead += count;
            }

View on GitHub (pinned to 290d5ab72c)

Solutions

  1. Collect full createdump diagnostics first: set DOTNET_CreateDumpDiagnostics=1 and DOTNET_CreateDumpVerboseDiagnostics=1 and reproduce; the child's earlier 'Problem reading ... child_read_pipe' line is the real root cause.
  2. Check whether the process is being killed externally during crash handling (dmesg for oom-killer, container runtime OOM events) and raise memory limits or disable the reaper.
  3. Ensure no third-party SIGCHLD handler / init system (e.g. dumb-init, tini in PID-1 reap mode) is reaping the createdump child before the parent writes.
  4. Raise the open-files limit (ulimit -n) if the crash path is running out of pipe fds.
  5. If the environment cannot support out-of-proc dumps, unset DOTNET_DbgEnableMiniDump and rely on the OS core pattern (coredumpd/apport) instead.

Example fix

# before
$ DOTNET_DbgEnableMiniDump=1 ./app
# Problem writing to createdump parent_write_pipe: Broken pipe (32)

# after: enable diagnostics to see the child's preceding failure
$ DOTNET_DbgEnableMiniDump=1 \
  DOTNET_CreateDumpDiagnostics=1 \
  DOTNET_CreateDumpVerboseDiagnostics=1 \
  ./app
Defensive patterns

Strategy: validation

Validate before calling

# Before relying on minidumps, verify the crash path can keep the parent/child pipe alive.
[ "$(ulimit -n)" -ge 1024 ] || ulimit -n 65536
# Ensure no PID-1 reaper will steal or kill the child; if using --init, test dump capture once:
DOTNET_DbgEnableMiniDump=1 DOTNET_CreateDumpVerboseDiagnostics=1 ./app & sleep 1; kill -ABRT $!; wait $!
ls -l *.dmp 2>/dev/null || echo "WARN: dump handshake unreliable in this environment"

Prevention

When it happens

Trigger: DOTNET_DbgEnableMiniDump=1 is set and the process crashes; the forked child dies during setup (for example it hit the 'Problem reading from createdump child_read_pipe' branch at line 258 and called exit(-1)) before the parent's write() completes. It can also fire if the parent itself is interrupted (signal) such that the write returns 0 or a non-EINTR error, or if the pipe fds were invalidated.

Common situations: Child perished first because the child_read_pipe read failed (parent never wrote, or parent died in the prctl path); the process was SIGKILLed by the OOM killer or a container reaper between fork and the parent's write; a custom SIGCHLD reaper or signal handler interfered; resource exhaustion (fd limit) left the pipe half-open.

Related errors


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