2011-02-25 489 views
2

我有以下小應用程序。在Windows 7QProcess卡住了

#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; 
} 

與MinGW的編譯器運行的Qt儘管一切努力,運行此程序後,我得到的唯一輸出是:

QProcess: Destroyed while process still running 

我不知道我做錯了什麼,或者我錯過了一些東西。我改變了waitForFinished電話waitForReadyRead我自己設置了閱讀頻道,都無濟於事。現在我正式需要幫助,因爲我不想實施我自己的grep。

回答

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

注:我已經有了與Python的子進程模塊相同的問題。至少他們的文件在這個問題上已經夠清楚了。建議的替代方案實現了這種主動迴路。 (http://docs.python.org/library/subprocess.html#subprocess.Popen.wait) – 2011-02-25 15:43:29

+0

謝謝,這個確切的代碼做的工作 – Sambatyon 2011-02-25 16:12:04

0

幾件事情:

1)你應該叫waitForStarted()開始後,要等到它的啓動和運行。 2)你不想在頂端附近調用waitForFinished(),因爲它會一直等到它完成(默認等待30秒)。

3)在完成查找輸出後,您可能確實希望在最後調用waitForFinished()(在大多數操作系統中,您需要讓進程返回正確的退出狀態並等待它;實際上我不是Qt是如何處理這一點的,說實話,你是否必須在較高的代碼中執行waitForFinished()或是否讓較低的Qt代碼可以忽略這個要求)