QProcess卡住了

时间:2011-02-25 11:27:46

标签: c++ qt4 mingw

我有以下小应用程序。在Windows 7中使用MinGW编译器运行Qt

#include <QProcess>
#include <QStringList>
#include <iostream>

const int64_t kBuffSize = 2048;

int main(int argc, char *argv[]) {
  QProcess grep;
  QStringList params;
  params << "-e" << "\".*pas'\"" << "\"Path to file\"";
  grep.start("C:\\MinGW\\msys\\1.0\\bin\\grep.exe", params);
  grep.setReadChannel(QProcess::StandardOutput);
  if (!grep.waitForFinished()) {
    if (grep.state() == QProcess::Running)
      grep.kill();
    return 1;
  }
  std::cout << "ready to read"  << std::endl;
  char buffer[kBuffSize];
  while (grep.readLine(buffer, kBuffSize) > 0) {
    std::cout << buffer;
  }
  if (grep.state() == QProcess::Running)
    grep.kill();
  return 0;
}

尽管付出了所有努力,但在运行此程序后,我得到的唯一输出是:

QProcess: Destroyed while process still running

我不知道我做错了什么,或者我错过了什么。我已经更改了waitForFinishedwaitForReadyRead的调用我自己设置了阅读频道,但都无济于事。现在我正式需要帮助,因为我不想实现自己的grep。

2 个答案:

答案 0 :(得分:5)

作为一种通用方式,您不希望在尝试读取之前运行进程并在系统管道中累积所有输出。这会导致死锁,特别是在Windows上。

系统对管道的缓冲区大小施加限制。发生的事情是子进程(grep)在写入管道时阻塞,因为缓冲区已满。它等待父进程(你的应用程序)从管道读取,释放缓冲区中的空间。现在,由于您的应用程序处于阻塞等待状态,等待进程完成,因此它们每个都在等待。

因为waitForFinish()默认等待最多30秒,所以在30秒结束时,你的应用程序会中断阻塞等待并返回,子进程仍然在运行并且你将其终止。

此问题的解决方案是一个活动的读取循环,用于在生成子进程输出时处理它,确保缓冲区中的可用空间,从而防止死锁。

我不是Qt的专家,所以我不确定如何在Qt中实现这个活动循环。看一下documentation for QProcess,我会说:

    // Use resizable buffers, unlike the system.
QByteArray stderr;
QByteArray stdout;

    // Give the child process some time to start.
grep.waitForStarted();
do {
        // Read all available data on both output streams.
    stderr += grep.readAllStandardError();
    stdout += grep.readAllStandardOutput();
}
    // Wait 100 ms and keep looping if not finished.
while ( !grep.waitForFinished(100) );

    // Make sure you catch any leftovers.
stderr += grep.readAllStandardError();
stdout += grep.readAllStandardOutput();

// Do something with the buffers.

答案 1 :(得分:0)

有几件事:

1)你应该在开始后调用waitForStarted(),等待它运行起来。

2)你不想在顶部附近调用waitForFinished(),因为它会等到它完成(默认等待30秒)。

3)你可能想要在完成查找输出后调用waitForFinished()(在大多数操作系统上你需要让进程返回正确的退出状态并等待它;我实际上并不是正面的Qt如何处理这个问题,说实话,以及你是否必须在更高的代码中执行waitForFinished(),或者更低的Qt代码是否会让你忽略这个要求)