我有一段代码执行一个过程并检索结果。

namespace {
    FILE* really_popen(const char* cmd, const char* mode) {
#ifdef _MSC_VER
        return _popen(cmd, mode);
#else
        return popen(cmd, mode);
#endif
    }
    void really_pclose(FILE* pipe) {
#ifdef _MSC_VER
        _pclose(pipe);
#else
        pclose(pipe);
#endif
    }
    std::string ExecuteProcess(std::string cmd) {
        FILE* pipe = really_popen(cmd.c_str(), "r");
        if (!pipe) throw std::runtime_error("Could not invoke command " + cmd);
        char buffer[128];
        std::string result = "";
        while(!feof(pipe)) {
            if(fgets(buffer, 128, pipe) != NULL)
                result += buffer;
        }
        really_pclose(pipe);
        return result;
    }
}

这对我在Linux上正常工作,但是在Windows上,它有一个死锁的可怕习惯-似乎fgets永不返回。我研究了CRT源,并且fgets最终将其委托(delegate)给ReadFile,但它永远不会返回。

如果我从命令行调用该命令,它将在一秒钟内返回。

如何在Windows上读取输出而不会死锁父级?

最佳答案

如果该子项尚未退出,则对fgets()的调用不会退出,因此您需要解决该子项未退出的原因。在这种情况下,最有可能的原因是 child 因为没有标准输入而被挂起。

如果那是问题,则可以通过将管道模式更改为“rw”来解决。您通常不需要对多余的管道做任何事情,只需要在那儿就可以了。

(正如您在注释中提到的,也可以通过使用命令 shell 重定向为子级提供NUL的句柄作为标准输入来解决该问题。)

10-02 06:50