QProcess не завершается при вызове из Qthread

Я пытаюсь установить RPM с помощью QProcess(/bin/rpm). Этот QProcess работает в параллельном потоке, запущенном другим QThread.

       QThread retThread = new CMyThread(this);
       connect(retThread, SIGNAL(finished()), retThread, SLOT(deleteLater()));
       retThread->start();

По какой-то причине QProcess продолжает работать и никогда не завершается. Когда я получаю pid QProcess и проверяю его с помощью команды ps, я не вижу ни одной выполняемой команды rpm. Стандартный выход и стандартная ошибка объединяются в один канал и регистрируются в файле.

Журнал показывает, что команда rpm завершила процесс установки.

Такое же поведение не наблюдается, когда я запускаю установку rpm с помощью QProcess в основном потоке. Это что-то, связанное с циклом событий. Если да, то как проверить, существует ли цикл событий. Насколько мне известно, поток должен автоматически создавать цикл событий из QT 4.4 и выше. Я использую QT 4.8

http://qt-project.org/wiki/Threads_Events_QObjects

Я чувствую, что цикл событий существует, так как в этом потоке я получаю другие сигналы очереди потока.

   QString ORIGINAL_LOG_FILE = "/var/Component.log";

    int PROC_WAIT_TIME= 90000;
    QSharedPointer<QProcess>  process(new QProcess);


    QString program = "/bin/rpm";
    QStringList compArgs;

    compArgs << "-Uvh"<<"--nodeps"<<"some.rpm";


    QStringList configEnvironmentVars = process->systemEnvironment();


    process->setEnvironment(configEnvironmentVars);

    process->setWorkingDirectory("/tmp/something");

    connect(process.data() , SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slot_finished(int,QProcess::ExitStatus)) );

    // process->setWorkingDirectory();
    process->setProcessChannelMode(QProcess::MergedChannels);
    process->setStandardOutputFile(ORIGINAL_LOG_FILE, QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text);
    process->start(program, compArgs);

    if (process->waitForStarted())
    {
      LOGINFO(m_nodeLogFile,QString("Waiting for the process to finish"));
      do
      {
         LOGINFO(m_nodeLogFile, QString("pid = %1").arg((uint)process->pid()));
         LOGINFO(m_nodeLogFile , QString("Error = %1").arg(process->error()));
         LOGINFO(m_nodeLogFile,QString("Envirnoment variables = %1").arg(configEnvironmentVars.join("\n")));
         LOGINFO(m_nodeLogFile,QString("Working directory = %1").arg(process->workingDirectory()));
         LOGINFO(m_nodeLogFile,QString("State = %1").arg(process->state()));
      }while(!process->waitForFinished(100));

Я даже пытался подключиться к финишному сигналу.


person Srikan    schedule 03.05.2013    source источник


Ответы (2)


Чтобы использовать слоты и сигналы в другом потоке, вам необходимо запустить цикл обработки событий.

Внутри метода run вашего потока вам нужно вызвать exec .

При необходимости вы можете выполнить настройку и демонтаж до и после, например:

void MyThread::run()
{
  // Setup code here
  exec();
  // Tear-down code here
}

Чтобы выйти из цикла событий и завершить поток, вы можете вызвать слот exit в потоке.

Реализация QThread::run() по умолчанию будет просто вызывать exec, но если вы повторно реализуете run, вам нужно будет вызвать exec самостоятельно.

Для получения дополнительной информации см. Подклассы QThread раздел в инструкции.

person Silas Parker    schedule 04.05.2013

Причина в том, что мы использовали mongoose HTTP-сервера с открытым исходным кодом. В открытом исходном коде сигнал SIGCHLD был отключен для всего приложения.

 void signal(SIGCHLD , SIG_IGN);

Раньше это приводило к тому, что все приложение не получало дочерний сигнал выхода. QProcess должен обработать этот сигнал, чтобы определить, завершился ли дочерний процесс.

person Srikan    schedule 06.05.2013