简体   繁体   English

QProcess卡住了

[英]QProcess is stuck

I have the following small application. 我有以下小应用程序。 Running Qt with MinGW compiler in Windows 7 在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;
}

Despite all efforts, after running this program the only output I get is: 尽管付出了很多努力,但在运行此程序后,我得到的唯一输出是:

QProcess: Destroyed while process still running

I don't know if I am doing something wrong, or I am missing something. 我不知道我做错了什么,或者我错过了什么。 I have change the waitForFinished call for waitForReadyRead I setted up the read channel myself, all to no avail. 我修改了waitForFinished呼吁waitForReadyRead我设置好的了读取信道自己,都无济于事。 Now I officially need help since I don't want to implement my own grep. 现在我正式需要帮助,因为我不想实现自己的grep。

As a general fashion, you don't want to run a process and accumulate all it's output in a system pipe before trying to read. 作为一种通用方式,您不希望在尝试读取之前运行进程并在系统管道中累积其所有输出。 This is know to cause deadlocks, especially on Windows. 这会导致死锁,特别是在Windows上。

The system imposes a limit on the buffer size for the pipe. 系统对管道的缓冲区大小施加限制。 What happens is that the child process (grep) blocks on a write to the pipe because the buffer is full. 发生的事情是子进程(grep)在写入管道时阻塞,因为缓冲区已满。 It waits for the parent process (you app) to read from the pipe, freeing space in the buffer. 它等待父进程(你的应用程序)从管道读取,释放缓冲区中的空间。 Now, since your applications is in a blocking wait, waiting for the process to finish, they're each waiting after each other. 现在,由于您的应用程序处于阻塞等待状态,等待进程完成,因此它们每个都在等待。

Because waitForFinish() waits at most 30 seconds by default, at the end of 30 seconds, your application breaks the blocking wait and returns, the child process is still running and you kill it. 因为waitForFinish()默认等待最多30秒,所以在30秒结束时,应用程序会中断阻塞等待并返回,子进程仍然在运行并且您将其终止。

The solution to this problem is an active read loop to process the child process output as it is generated, ensuring free space in the buffer and thus preventing the deadock. 此问题的解决方案是一个活动的读取循环,用于在生成子进程输出时处理子进程输出,从而确保缓冲区中的可用空间,从而防止死锁。

I'm no expert in Qt, so I'm not sure how to implement this active loop in Qt. 我不是Qt的专家,所以我不确定如何在Qt中实现这个活动循环。 Taking a look at the documentation for QProcess , I'd say something like: 看一下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.

A couple of things: 有几件事:

1) you should probably call waitForStarted() after the start to wait until it's up and running. 1)你可能应该在启动后调用waitForStarted(),直到它启动并运行。

2) you don't want to call waitForFinished() near the top, because it'll wait until it's done (defaulting to waiting for 30 seconds). 2)你不想在顶部附近调用waitForFinished(),因为它会等到它完成(默认等待30秒)。

3) You probably do want to call waitForFinished() at the end after you're done looking for output (on most OSes you need to let the process return a proper exit status and wait for it; I actually am not positive how Qt deals with this, to be honest, and whether you must perform a waitForFinished() in the higher code or whether the lower Qt code will let you ignore this requirement) 3)你可能想要在完成查找输出后调用waitForFinished()(在大多数操作系统上你需要让进程返回正确的退出状态并等待它;我实际上并不认为Qt是如何处理的有了这个,说实话,你是否必须在更高的代码中执行waitForFinished()或者更低的Qt代码是否会让你忽略这个要求)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM