Почему эта программа не работает (иногда)? - PullRequest
2 голосов
/ 11 ноября 2009
#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

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

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

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

Ответы [ 2 ]

3 голосов
/ 11 ноября 2009

Ваш 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 голосов
/ 11 ноября 2009
#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;
...