1

我正在尝试使用 QProcess(/bin/rpm) 安装 RPM。此 QProcess 正在由另一个 QThread 启动的并发线程中运行。

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

由于某种原因,QProcess 继续运行并且永远不会退出。当我得到 QProcess 的 pid 并使用 ps 命令检查时,我没有看到任何正在执行的 rpm 命令。标准输出和标准错误都合并到一个通道并登录到一个文件。

该日志表明 rpm 命令已完成安装过程。

当我在主线程上使用 QProcess 运行 rpm 安装时,没有看到相同的行为。这是否与事件循环有关。如果是这样如何检查事件循环是否存在。据我所知,线程应该自动从 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));

我什至尝试连接到完成信号。

4

2 回答 2

1

要在另一个线程中使用槽和信号,您需要运行一个事件循环。

run线程的方法中,您需要调用exec.

如果需要,您可以在前后进行设置和拆卸,例如:

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

要离开事件循环并完成您的线程,您可以调用exit线程上的插槽。

默认实现QThread::run()只会调用exec,但如果你重新实现,run那么你需要exec自己调用。

有关更多信息,请查看手册中的Subclassing QThread部分。

于 2013-05-04T20:23:54.223 回答
0

原因在于我们使用的开源 HTTP 服务器 mongoose。在开源代码中,整个应用程序都禁用了 SIGCHLD 信号。

 void signal(SIGCHLD , SIG_IGN);

这曾经导致整个应用程序不接收子退出信号。QProcess 需要处理这个信号来确定子进程是否已经退出。

于 2013-05-06T22:07:27.433 回答