【问题标题】:QProcess is stuckQProcess 卡住了
【发布时间】:2011-02-25 11:27:46
【问题描述】:

我有以下小应用程序。在 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

我不知道我做错了什么,或者我错过了什么。我已将waitForFinished 呼叫更改为waitForReadyRead 我自己设置了读取通道,但均无济于事。现在我正式需要帮助,因为我不想实现自己的 grep。

【问题讨论】:

    标签: c++ qt4 mingw


    【解决方案1】:

    作为一般方式,您不希望在尝试读取之前运行进程并在系统管道中累积所有它的输出。这会导致死锁,尤其是在 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.
    

    【讨论】:

    【解决方案2】:

    有几点:

    1) 您可能应该在启动后调用 waitForStarted() 以等待它启动并运行。

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

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

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 2021-10-08
      • 2016-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多