dotnet/runtime · error
dup2(stdout) failed: %s\n
Error message
dup2(stdout) failed: %s\n
What it means
In ParallelSuperPMI's StartProcess the forked child redirects its stdout to a captured pipe handle with dup2(hStdOutput,STDOUT_FILENO). If dup2 returns -1 the child prints this message with strerror(errno) and _exit(1); the worker never execs and the parent sees a dead child. This is a child-side fatal during parallel worker launch.
Source
Thrown at src/coreclr/tools/superpmi/superpmi/parallelsuperpmi.cpp:215
return false;
}
*pid = fork();
if (*pid == -1)
{
LogError("fork() failed: %s", strerror(errno));
for (int i = 0; i < argc; i++)
delete[] argv[i];
delete[] argv;
return false;
}
if (*pid == 0)
{
// Child process: redirect stdout and stderr then exec.
if (dup2(hStdOutput, STDOUT_FILENO) == -1)
{
fprintf(stderr, "dup2(stdout) failed: %s\n", strerror(errno));
_exit(1);
}
if (dup2(hStdError, STDERR_FILENO) == -1)
{
fprintf(stderr, "dup2(stderr) failed: %s\n", strerror(errno));
_exit(1);
}
// Close the original fds now that they are duplicated to STDOUT/STDERR.
// The O_CLOEXEC on the parent's open() handles the sibling worker fds.
if (hStdOutput != STDOUT_FILENO)
close(hStdOutput);
if (hStdError != STDERR_FILENO)
close(hStdError);
execv(argv[0], argv);
// If execv returns, it failed.
fprintf(stderr, "execv(%s) failed: %s\n", argv[0], strerror(errno));View on GitHub (pinned to 60108ba66e)
Solutions
- Raise the file-descriptor limit before running parallelsuperpmi (ulimit -n 1048576) so worker pipes fit.
- Reduce the worker count (--workers/-j) so each child needs fewer fds.
- Check the pipe-open code path that produced hStdOutput for an early close or error being ignored.
- Run parallelsuperpmi under strace -f -e dup2 to see the failing errno and descriptor value.
Defensive patterns
Strategy: validation
Validate before calling
// Raise the fd limit before launching many parallel workers.
#include <sys/resource.h>
static bool RaiseFdLimit(rlim_t want) {
struct rlimit r;
if (getrlimit(RLIMIT_NOFILE, &r) != 0) return false;
if (r.rlim_cur >= want) return true;
r.rlim_cur = want < r.rlim_max ? want : r.rlim_max;
return setrlimit(RLIMIT_NOFILE, &r) == 0;
} Prevention
- Call setrlimit(RLIMIT_NOFILE) or ulimit -n before running parallelsuperpmi.
- Size the worker count so (workers * pipes) fits under the fd limit.
- Check open()/pipe() return values before passing descriptors to dup2.
- strace -f -e dup2 to catch the failing descriptor and errno.
When it happens
Trigger: hStdOutput is not a valid open descriptor (already closed or never opened), the process has exhausted file descriptors (EMFILE), or the target descriptor is invalid. Occurs only inside the forked worker before execv in parallelsuperpmi.
Common situations: Launching hundreds of parallel workers and hitting the per-process fd limit; a bug/race where the output pipe was closed before dup2; running ParallelSuperPMI with an fd ulimit too low for the worker count.
Related errors
- dup2(stderr) failed: %s\n
- execv(%s) failed: %s\n
- Error: Fail to PAL_Initialize\n
- Error: Fail to PAL_InitializeDLL\n
- Error: Fail to PAL_InitializeDLL\n
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/6050b9ba6111023d.
Report an issue: GitHub.