2009-11-10 9 views
2
#include <cstdio> 
#include <QtCore/QProcess> 

int main (int argc, char** argv) { 
    // if we remove 3 following lines, the problem described below doesn't exists!! 
    QProcess process; 
    process.start ("asdqwe"); // doesn't matter what we try to execute here. 
    process.waitForStarted (1000); 

    while (true) { 
    char buf[100]; 
    if (scanf ("%s", buf) == EOF) { // it looks like stdin is closed! 
     printf("FAIL\n"); 
     return 1; 
    } 
    printf ("%s\n", buf); 
    } 
    return 0; 
} 

Этот код является всего лишь фрагментом, чтобы показать проблему. В полном приложении мне нужно чтение/запись связи с процессом.Почему эта программа не работает (иногда)?

я скомпилировать его с:

g++ -o out ./main.cpp -I /usr/include/qt4/ -lQtCore 

И выполнить его из Баш командной строки в терминале.

Почему эта программа иногда печатает FAIL и иногда остается в цикле?

Редактировать: Это не вопрос о сканировании/печати. Та же проблема, если я использую iostreams + string. Этот вопрос касается взаимодействия QProcess с файловыми дескрипторами родительского процесса.

+0

All код показан. Возьмите его, скомпилируйте и запустите. –

+0

... и вы увидите странное поведение (по крайней мере, под Linux) –

+0

Ошибка была включена. исправлено. –

ответ

3

Ваш scanf был прерван сигналом SIGCHLD, который был пойман, когда дочерний процесс завершен. В этом случае также возвращается EOF.

QProcess материал имеет установить обработчик сигнала для SIGCHLD (проверка источников): (4.5.3 здесь)

Q_GLOBAL_STATIC(QProcessManager, processManager) 

QProcessManager::QProcessManager() 
{ 
#if defined (QPROCESS_DEBUG) 
    qDebug() << "QProcessManager::QProcessManager()"; 
#endif 
    // initialize the dead child pipe and make it non-blocking. 
    // (pipe and fcntl skipped - P. Shved.) 

    // set up the SIGCHLD handler, which writes a single byte to the dead 
    // child pipe every time a child dies. 
    struct sigaction oldAction; 
    struct sigaction action; 
    memset(&action, 0, sizeof(action)); 
    action.sa_handler = qt_sa_sigchld_handler; 
    action.sa_flags = SA_NOCLDSTOP; 
    ::sigaction(SIGCHLD, &action, &oldAction); 
    if (oldAction.sa_handler != qt_sa_sigchld_handler) 
     qt_sa_old_sigchld_handler = oldAction.sa_handler; 
} 
+0

А, это кажется правдоподобным. Спасибо, Павел. Но что мне тогда делать? Как я могу отличить SIGCHLD от реального EOF? Как это можно сделать с помощью кросс-платформы? –

+0

Вы должны проверить 'errno == EINTR'. Работает на Linux; в Windows есть одинаковые переменные, но я не уверен, как они работают на * этой * платформе. Или - просто используйте 'cin >> s' –

+0

cin >> s имеет точно такую ​​же проблему. –

0
#include <cstdio> 
#include <QtCore/QProcess> 

int main (int argc, char** argv) { 
    // if we remove 3 following lines, the problem described below doesn't exists!! 
    QProcess process; 
    process.start ("asdqwe"); // doesn't matter what we try to execute here. 
    process.waitForStarted (1000); 

    while (true) { 
    char buf[100]; 
    if (scanf ("%s", buf) == EOF) { // it looks like stdin is closed! 
     if (errno == EINTR) { 
     errno = 0; 
     continue; 
     } 
     printf("FAIL\n"); 
     return 1; 
    } 
    printf ("%s\n", buf); 
    } 
    return 0; 
} 

Я действительно использовать потоки, я должен был использовать

cin.clear(); 
errno = 0; 
Смежные вопросы