gpt4 book ai didi

c++ - waitpid/wexitstatus 返回 0 而不是正确的返回码

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:40:22 24 4
gpt4 key购买 nike

我有下面的辅助函数,用于在 posix 系统上执行命令并获取返回值。我曾经使用 popen , 但不可能通过 popen 获取应用程序的返回码如果它在 popen 之前运行并退出/pclose有机会完成它的工作。

以下辅助函数创建一个进程分支,使用 execvp运行所需的外部进程,然后父级使用 waitpid获取返回码。我看到它拒绝运行的奇怪情况。

当用 wait 调用时= true , waitpid无论如何都应该返回应用程序的退出代码。但是,我看到了 stdout指定返回码的输出应为非零,但返回码为零。在常规 shell 中测试外部进程,然后 echo荷兰国际集团$?返回非零值,因此外部进程未返回正确代码不是问题。如果有帮助,正在运行的外部进程是 mount(8) (是的,我知道我可以使用 mount(2),但这不是重点)。

对于代码转储,我提前表示歉意。其中大部分是调试/日志记录:

inline int ForkAndRun(const std::string &command, const std::vector<std::string> &args, bool wait = false, std::string *output = NULL)
{
std::string debug;

std::vector<char*> argv;
for(size_t i = 0; i < args.size(); ++i)
{
argv.push_back(const_cast<char*>(args[i].c_str()));
debug += "\"";
debug += args[i];
debug += "\" ";
}
argv.push_back((char*)NULL);

neosmart::logger.Debug("Executing %s", debug.c_str());

int pipefd[2];

if (pipe(pipefd) != 0)
{
neosmart::logger.Error("Failed to create pipe descriptor when trying to launch %s", debug.c_str());
return EXIT_FAILURE;
}

pid_t pid = fork();

if (pid == 0)
{
close(pipefd[STDIN_FILENO]); //child isn't going to be reading
dup2(pipefd[STDOUT_FILENO], STDOUT_FILENO);
close(pipefd[STDOUT_FILENO]); //now that it's been dup2'd
dup2(pipefd[STDOUT_FILENO], STDERR_FILENO);

if (execvp(command.c_str(), &argv[0]) != 0)
{
exit(EXIT_FAILURE);
}
return 0;
}
else if (pid < 0)
{
neosmart::logger.Error("Failed to fork when trying to launch %s", debug.c_str());
return EXIT_FAILURE;
}
else
{
close(pipefd[STDOUT_FILENO]);

int exitCode = 0;

if (wait)
{
waitpid(pid, &exitCode, wait ? __WALL : (WNOHANG | WUNTRACED));

std::string result;
char buffer[128];
ssize_t bytesRead;
while ((bytesRead = read(pipefd[STDIN_FILENO], buffer, sizeof(buffer)-1)) != 0)
{
buffer[bytesRead] = '\0';
result += buffer;
}

if (wait)
{
if ((WIFEXITED(exitCode)) == 0)
{
neosmart::logger.Error("Failed to run command %s", debug.c_str());
neosmart::logger.Info("Output:\n%s", result.c_str());
}
else
{
neosmart::logger.Debug("Output:\n%s", result.c_str());
exitCode = WEXITSTATUS(exitCode);
if (exitCode != 0)
{
neosmart::logger.Info("Return code %d", (exitCode));
}
}
}

if (output)
{
result.swap(*output);
}
}

close(pipefd[STDIN_FILENO]);

return exitCode;
}
}

请注意,使用正确的参数可以正常运行该命令,函数继续运行没有任何问题,WIFEXITED返回 TRUE .然而,WEXITSTATUS当它应该返回其他内容时返回 0。

最佳答案

可能不是您的主要问题,但我认为我发现了一个小问题。在您的子进程中,您有...

dup2(pipefd[STDOUT_FILENO], STDOUT_FILENO);
close(pipefd[STDOUT_FILENO]); //now that it's been dup2'd
dup2(pipefd[STDOUT_FILENO], STDERR_FILENO); //but wait, this pipe is closed!

但我认为你想要的是:

dup2(pipefd[STDOUT_FILENO], STDOUT_FILENO);
dup2(pipefd[STDOUT_FILENO], STDERR_FILENO);
close(pipefd[STDOUT_FILENO]); //now that it's been dup2'd for both, can close

我对 Linux 中的 fork 和 pipes 没有太多经验,但最近我确实写了一个类似的函数。如果愿意,您可以查看代码进行比较。我知道我的功能有效。

execAndRedirect.cpp

关于c++ - waitpid/wexitstatus 返回 0 而不是正确的返回码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13182100/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com