서브 프로세스를 실행하고 표준 출력에서 데이터를 읽는 Qt 애플리케이션의 겉으로보기에는 간단한 부분을 코딩하는 동안, 나는 정말 당황 스럽다. 애플리케이션은 구성 프로세스에서 데이터 블록 (원시 비디오 프레임)을 읽고이 도착하여 처리해야명백한 이유없이 QProcess가 죽는다
-
한 프레임
- 프로세스 프레임 충분히 존재할 때까지
- 데이터가 모이는 QProcess 시작 2
단계로
app::app() {
process.start("cat /dev/zero");
buffer = new char[frameLength];
connect(this, SIGNAL(wantNewFrame()), SLOT(readFrame()), Qt::QueuedConnection);
connect(this, SIGNAL(frameReady()), SLOT(frameHandler()), Qt::QueuedConnection);
emit wantNewFrame();
}
내가 여기 사소한 과정 (cat /dev/zero
) 우리는 데이터가 부족하지 않을 것을 확신 할 수 있도록를 시작합니다. 또한 두 개의 연결을 만듭니다. 하나는 프레임이 필요할 때 읽기를 시작하고 다른 하나는 프레임이 도착하면 데이터 처리 함수를 호출합니다. 이 간단한 예제는 단일 스레드에서 실행되므로 무한 재귀를 피하기 위해 대기열 유형으로 연결됩니다. wantNewFrame()
신호는 첫 번째 프레임의 수집을 시작합니다. 컨트롤이 이벤트 루프로 반환 될 때 처리됩니다.
bool app::readFrame() {
qint64 bytesNeeded = frameLength;
qint64 bytesRead = 0;
char* ptr = buffer;
while (bytesNeeded > 0) {
process.waitForReadyRead();
bytesRead = process.read(ptr, bytesNeeded);
if (bytesRead == -1) {
qDebug() << "process state" << process.state();
qDebug() << "process error" << process.error();
qDebug() << "QIODevice error" << process.errorString();
QCoreApplication::quit();
break;
}
ptr += bytesRead;
bytesNeeded -= bytesRead;
}
if (bytesNeeded == 0) {
emit frameReady();
return true;
} else
return false;
}
프레임 읽기 : 기본적으로 데이터가 도착하면 버퍼에 채워집니다. 끝에있는 frameReady()
신호는 프레임이 준비되었음을 알리고 데이터 처리 기능을 실행합니다.
void app::frameHandler() {
static qint64 frameno = 0;
qDebug() << "frame" << frameno++;
emit wantNewFrame();
}
간단한 데이터 프로세서 : 프레임 수만 계산합니다. 완료되면 wantNewFrame()
을 발급하여 새 읽기주기를 시작합니다.
이것은 그 것이다. 완성을 위해 헤더 파일과 main()을 여기에 게시 할 것입니다.
APP_H, :
#include <QDebug>
#include <QCoreApplication>
#include <QProcess>
class app : public QObject
{
Q_OBJECT
public:
app();
~app() { delete[] buffer; }
signals:
void wantNewFrame();
void frameReady();
public slots:
bool readFrame();
void frameHandler();
private:
static const quint64 frameLength = 614400;
QProcess process;
char* buffer;
};
MAIN.CPP : 기괴한 부분에 대한
#include "app.h"
int main(int argc, char** argv)
{
QCoreApplication coreapp(argc, argv);
app foo;
return coreapp.exec();
}
그리고 지금. 이 프로그램은 잘 프레임의 임의의 숫자를 (I 이상 만에 다섯 아무것도 본 적이) 처리하지만 결국 중단하고 QProcess 추락했다고 불평 : 프로세스 상태 0을 의미
$ ./app
frame 1
...
frame 245
frame 246
frame 247
process state 0
process error 1
QIODevice error "Process crashed"
은 "실행되지"와 프로세스 오류 1은 "충돌"을 의미합니다. 나는 그것에 대해 조사한 결과, 자식 프로세스가 SIGPIPE를 받았다는 것을 알았습니다. 즉, 부모가 파이프를 닫았습니다. 그러나 나는 을 전혀 가지고 있지 않다. 아이디어는 어디서 그리고 왜 일어나는가? 다른 사람 있습니까?
깔끔한 제안이지만, 불행히도 strace에서 많은 도움이되는 정보를 얻지 못했습니다. 그러나 파이프가 실제로 닫혀 있음을 확인했습니다. 나는 잘못된 일을하지 않을 것이며 Qt의 내부 경쟁 조건으로 인해 문제가 발생한다고 생각하기 시작했습니다. –
그건 위험한 결론입니다. PosPro syscalls로 QProcess를 재미로 재 작성하려고 시도한 사람으로서, 나는 그것을 유혹 할 수 있음을 인정합니다 :). 확실하게''strace''의 출력에서''close()''를 볼 수 있습니다. 이것이 왜 발생하는지 알기에 충분하지 않다면,''gdb''와 같은 디버거에서 모든 것을 실행하고 "close"에 중단 점/catchpoint를 설정할 수 있습니다. –
나는 Qt의 코드를 다소 파고 있었고 close()가 호출 된 곳을 찾았습니다. 이제 ... 하하하! 나는이 문제와 관련이있을 수있는 Qt 관심사에 대한 전자 메일 스레드에 대한 링크를 붙여 넣으 려하고 있었으며 이제는 스레드를 시작한 사람이 누구인지 알게되었습니다. :-) 음, [여기] (http://lists.qt.nokia.com/public/qt-interest/2009-May/006341.html)는 어쨌든 링크입니다. 무슨 일이 일어나고 있는지에 대한 내 인상은 메인 이벤트 루프가 파이프에 대기중인 새 데이터에 대해 어떻게 든 잘못된 알림을 받으면서 실제로는 아무 것도 없다는 것을 알게됩니다. –