重定向标准输出时调用 dup2 失败
Call to dup2 fails when redirecting stdout
我已经为此苦苦挣扎了一段时间。我正在尝试围绕运行子进程编写一个C++类。我正在使用fork()
、pipe()
、dup2()
和execv()
来启动子进程并将其标准输出和标准重定向到父进程。据我所知,一切都很好,直到调用dup2()
并且它因EINVAL
而失败(在 macOS 上,我认为这不是 Linux 中允许的错误类型)。如果我删除管道周围的所有逻辑,该类将按预期工作。
类声明:
class PosixSubprocess : public Subprocess {
std::string _cmd = {};
std::string _stdout = "";
std::string _stderr = "";
std::vector<std::string> _args = {};
long _pid = -1;
int _status = -1;
public:
void cmd(std::string val) override;
void addArg(std::string val) override;
void run() override;
int status() const override;
std::string out() const override;
std::string err() const override;
};
run()
的定义:
void PosixSubprocess::run() {
std::array<int, 2> stdoutPipe = {};
std::array<int, 2> stderrPipe = {};
if (pipe(stdoutPipe.data()) < 0)
{
throw std::runtime_error("Subprocess: failed to create pipes. Errno: " + std::to_string(errno));
}
if (pipe(stderrPipe.data()) < 0)
{
throw std::runtime_error("Subprocess: failed to create pipes. Errno: " + std::to_string(errno));
}
_pid = fork();
if (_pid == 0) {
if (dup2(stderrPipe[1], STDERR_FILENO)) {
std::cout << "Subprocess: failed to redirect stderr. Errno " << errno << 'n';
exit(errno);
}
if (dup2(stdoutPipe[1], STDOUT_FILENO)) {
std::cout << "Subprocess: failed to redirect stdout. Errno " << errno << 'n';
exit(errno);
}
close(stdoutPipe[0]);
close(stdoutPipe[1]);
close(stderrPipe[0]);
close(stderrPipe[1]);
auto argv = std::make_unique<char*[]>(_args.size() + 1);
argv[_args.size()] = nullptr;
for (size_t i = 0; i < _args.size(); ++i) {
argv[i] = &(_args[i].front());
}
if(execvp(_cmd.c_str(), argv.get())) {
std::cerr << "Subprocess: failed to launch. Errno " << errno << 'n';
exit(errno);
}
} else if (_pid > 0) {
close(stdoutPipe[1]);
close(stderrPipe[1]);
std::array<char, 1024> buf;
auto appendPipe = [&buf](int fd, std::string& str) {
ssize_t nBytes = 0;
do {
nBytes = read(fd, buf.data(), buf.size());
str.append(buf.data(), nBytes);
if (nBytes) std::cout << nBytes << 'n';
} while (nBytes > 0);
};
while(!waitpid(_pid, &_status, WNOHANG)) {
appendPipe(stdoutPipe[0], _stdout);
appendPipe(stdoutPipe[0], _stderr);
}
} else {
close(stdoutPipe[0]);
close(stdoutPipe[1]);
close(stderrPipe[0]);
close(stderrPipe[1]);
throw std::runtime_error("Subprocess: fork failed.");
}
}
很抱歉这里的代码墙,我不能肯定地说与问题无关。
来自dup2
的手册页:
返回值
成功完成后,应返回一个非负整数,即文件描述符;否则,应返回 -1 并设置 errno 以指示错误。
由于显然,dup2()
返回原始文件描述符,并且它不为零,因此显示的代码认为这是一个错误。
错误条件由负返回值指示。
相关文章:
- 如果没有malloc,链表实现将失败
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 视图中的参数推导失败:take_while
- 链接到自行创建的dll失败
- 带有特殊路径部分的"std::filesystem::weakly_canonical"失败
- GetShortPathName在网络驱动器上使用中文文件夹时失败
- gcc和c++17的过载解析失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在WSL:configure_file上对config_file的每次调用都失败:配置文件时出现问题
- 使用 GCC 卸载的 OpenMP 卸载失败,并出现"Ptx assembly aborted due to errors"
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- 链接阶段在Ubuntu上失败,但在MacOS上失败
- 从父数组测试用例构造二叉树失败
- LibGit2 SSH身份验证失败
- 如何让LLDB在成功时退出,在失败时等待
- VS2017,C++包含目录与附加包含目录,子文件夹包含失败-但为什么
- 生成MRPT库时cmake配置失败
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 重定向标准输出时调用 dup2 失败