English 中文(简体)
终止在 QTread 内运行的当前进程? [重复]
原标题:Terminate an ongoing QProcess that is running inside a QThread? [duplicate]

how to terminate an ongoing QProcess that is running inside a QThread and gets deleted by another QThread? I even inserted a QMutex extCmdProcessLock, which should avoid the destruction of the DbManager before the extCmdProcess could finish or timeout. I get a segmentation fault on "waitForStarted" if another thread calls delete on DbManager. I cannot use signals (I think) because I use the external command inside a sequential data process. Thank you very much for any help!

DbManager::extCmd(){
    ...
    QMutexLocker locker(&extCmdProcessLock);
    extCmdProcess = new QProcess(this);
    QString argStr  += " --p1=1"
                    +  " --p2=3";
    extCmdProcess->start(cmd,argStr.split(QString(" ")));
    bool startedSuccessfully = extCmdProcess->waitForStarted();
    if (!startedSuccessfully) {
       extCmdProcess->close();
       extCmdProcess->kill();
       extCmdProcess->waitForFinished();
       delete extCmdProcess;
       extCmdProcess = NULL;
       return;
    }
    bool successfullyFinished = extCmdProcess->waitForFinished(-1);
    if (!successfullyFinished) {
       qDebug() << "finishing failed"; // Appendix C
       extCmdProcess->close();
       extCmdProcess->kill();
       extCmdProcess->waitForFinished(-1);
       delete extCmdProcess;
       extCmdProcess = NULL;
       return;
   }
   extCmdProcess->close();
   delete extCmdProcess;
   extCmdProcess = NULL;
}

DbManager::~DbManager(){
    qDebug() << "DB DbManager destructor called.";   
    QMutexLocker locker(&extCmdProcessLock);
    if (extCmdProcess!= NULL){
       this->extCmdProcess->kill(); // added after Appendix A
       this->extCmdProcess->waitForFinished();
    }
}

附录A: I also get the mistake "Qprocess: destroyed while process is still running." 我读到,这可能意味着在等待启动命令未完成时执行我其他线条中的“ 删除 dbmanager” 呼叫 。 但我真的想知道为什么我的毁灭器中的杀死() 命令没有解决这个问题 。 @ info: tooltip

附录B: 根据评论,添加了 wait forfinished () <()/code>。可悲的是,程序终止仍然不能正常关闭,分割错误发生在 waitforstarted() 或以下的 start() <()/code>本身。

#0  0x00007f25e03a492a in QEventDispatcherUNIX::registerSocketNotifier () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#1  0x00007f25e0392d0b in QSocketNotifier::QSocketNotifier () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#2  0x00007f25e0350bf8 in ?? () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#3  0x00007f25e03513ef in ?? () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#4  0x00007f25e03115da in QProcess::start () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#5  0x0000000000428628 in DbManager::extCmd()
#6  0x000000000042ca06 in DbManager::storePos ()
#7  0x000000000044f51c in DeviceConnection::incomingData ()
#8  0x00000000004600fb in DeviceConnection::qt_metacall ()
#9  0x00007f25e0388782 in QObject::event () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#10 0x00007f25e0376e3f in QCoreApplicationPrivate::notify_helper () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#11 0x00007f25e0376e86 in QCoreApplication::notify () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#12 0x00007f25e0376ba4 in QCoreApplication::notifyInternal () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#13 0x00007f25e0377901 in QCoreApplicationPrivate::sendPostedEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#14 0x00007f25e03a4500 in QEventDispatcherUNIX::processEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#15 0x00007f25e0375e15 in QEventLoop::processEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#16 0x00007f25e0376066 in QEventLoop::exec () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#17 0x00007f25e0277715 in QThread::exec () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#18 0x00007f25e027a596 in ?? () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#19 0x00007f25df9b43f7 in start_thread () from /lib/libpthread.so.0
#20 0x00007f25def89b4d in clone () from /lib/libc.so.6
#21 0x0000000000000000 in ?? ()

Appendix C: The debug output showed me, that the error message: QProcess: Destroyed while process is still running. always appears, when the finishing failed output appears. This means that my locks or/and kill attempts to protect the QProcess are failing. Questions I wonder about:

a) 如果创建并启动一个处理对象, 我的 < code> extCmdProcessLock 是否解锁? 我已经尝试使用普通的 < code> lock () 调用, 而不是 , 但没有运气 。

(b) 文档说,如果我这样使用进程,main 线 将会被停止。它们是否真的指“em>main 线 或启动进程时的线?

QProcess 是否在多线性环境中不适用? 如果两个线条创建了 QProcess 对象并运行它, 它们会干扰吗? 也许该对象是静态的?

谢谢你帮忙填补知识漏洞,我真希望解开这个谜题

<强> 附录D: 从任何线索删除任何删除和删除 Later () 后, 我的程序仍然被打碎 。

#0  0x00007fc94e9796b0 in QProcess::setProcessState () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#1  0x00007fc94e97998b in QProcess::waitForStarted () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#2  0x00007fc94e979a12 in QProcess::waitForFinished () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#3  0x0000000000425681 in DbManager::extCmd()
#4  0x0000000000426fb6 in DbManager::storePos ()
#5  0x000000000044d51c in DeviceConnection::incomingData ()
#6  0x000000000045fb7b in DeviceConnection::qt_metacall ()
#7  0x00007fc94e9f4782 in QObject::event () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#8  0x00007fc94e9e2e3f in QCoreApplicationPrivate::notify_helper () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#9  0x00007fc94e9e2e86 in QCoreApplication::notify () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#10 0x00007fc94e9e2ba4 in QCoreApplication::notifyInternal () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#11 0x00007fc94e9e3901 in QCoreApplicationPrivate::sendPostedEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#12 0x00007fc94ea10500 in QEventDispatcherUNIX::processEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#13 0x00007fc94e9e1e15 in QEventLoop::processEvents () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#14 0x00007fc94e9e2066 in QEventLoop::exec () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#15 0x00007fc94e8e3715 in QThread::exec () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#16 0x00007fc94e8e6596 in ?? () from /usr/local/Trolltech/Qt-4.7.4/lib/libQtCore.so.4
#17 0x00007fc94e0203f7 in start_thread () from /lib/libpthread.so.0
#18 0x00007fc94d5f5b4d in clone () from /lib/libc.so.6
#19 0x0000000000000000 in ?? ()
最佳回答

使用 QTread 来管理运行中的进程非常糟糕。 我一次又一次地看到它, 这是关于如何正确写入非同步应用程序的一些根本性误解。 进程与您自己的应用程序分开。 进程提供了一套美丽的信号, 以在它成功启动、 失败启动和完成时通知您 。 只需将这些信号挂在您的QObject派类的空位上, 您就会全部被设置 。

如果您应用程序中的线条数量大大超过平台上可用的核心/超链接数,或者线条数量与运行子进程的数量等一些不相关的运行时因数相关联,则其设计不善。

见我的另一个"https://stackoverflow.com/ questions/10799130/what-is-the-search-for-qprocess-error-status-510840448#10840448#10840448"[其他答复

您可以在堆肥上创建 QProcess, 作为您的监测 QObject 的子进程。 您可以将已完成的 QProcess s 信号连接到自己的删除Later () 槽, 以便当它完成时自动删除它。 监测 QObject 在它被销毁后, 应该强制终止任何剩余的运行进程, 例如由于您的应用程序关闭 。

进一步的问题是,如何执行无法控制的长期运行功能,在数据库查询时,在数据库查询没有非同步的API, 影响最小的情况下,如果在数据库查询有非同步的API, 诸如QProcess。

一种典型的方式是:在您必须同步进行的地方同步地进行操作, 以同样的方式。 您可以通过调用 deleteLater () 槽来停止控制对象和任何运行过程 -- -- 要么通过信号/ slot 连接, 要么通过 来阻止它, 如果您想在安全穿越线条边界时直接这样做的话。 这是使用尽可能少的阻塞电话的主要好处 : 您对处理程序有一些控制, 并且可以在一段时间内停止它。 在纯粹阻塞执行的情况下, 无法阻止它使用一些旗子变量, 并且用测试来复制您的代码 。

deleteLater () 将随时被处理, 事件循环可以在 QObject 生活的线索中旋转。 这意味着它会在数据库查询电话之间获得一个机会 -- -- 事实上, 在进程运行的任何时候。

未测试的代码 :

class Query : public QObject
{
  Q_OBJECT
public:
  Query(QObject * parent = 0) : QObject(parent) {
    connect(process, SIGNAL(error(QProcess::ProcessError)), SLOT(error()));
    connect(process, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(finished(int,QProcess::ExitStatus)));
  }
  ~Query() { process.kill(); }
  void start() {
    QTimer::singleShot(0, this, SLOT(slot1()));
  }
protected slots:
  void slot1() {
    // do a database query
    process.start(....);
    next = &Query::slot2;
  }
protected:
  // slot2 and slot3 don t have to be slots
  void slot2() {
    if (result == Error) {...}
    else {...}
    // another database query
    process.start(...); // yet another process gets fired
    next = &Query::slot3;
  }
  void slot3() {
    if (result == Error) {...}
    deleteLater();
  }

protected slots:
  void error() {
    result = Error;
    (this->*next)();
  }
  void finished(int code, QProcess::ExitStatus status) {
    result = Finished;
    exitCode = code;
    exitStatus = status;
    (this->*next)();
  }
private:
  QProcess process; 
  enum { Error, Finished } result;
  int exitCode;
  QProcess::ExitStatus exitStatus;
  void (Query::* next)();
};

个人而言, 我将检查您正在使用的数据库是否有一个非同步的 API 。 如果没有, 但是如果客户库有可用的源头, 那么我将做一个最小端口, 使用 Qt s 网络堆叠来使其保持无同步。 这样会降低管理费, 因为您不再有每个数据库连接的线条, 而当您接近饱和 CPU 时, 管理费就会上升: 通常, 要饱和 CPU, 您需要很多线条, 因为大多是闲置的。 使用不同步的界面, 上下文开关的数量会下降, 因为一个线条会处理数据库中的一包数据, 并且可以立即从不同连接中处理另一包包, 而不必做上下文开关: 执行会停留在该线索的事件循环中 。

问题回答




相关问题
Signed executables under Linux

For security reasons, it is desirable to check the integrity of code before execution, avoiding tampered software by an attacker. So, my question is How to sign executable code and run only trusted ...

encoding of file shell script

How can I check the file encoding in a shell script? I need to know if a file is encoded in utf-8 or iso-8859-1. Thanks

How to write a Remote DataModule to run on a linux server?

i would like to know if there are any solution to do this. Does anyone? The big picture: I want to access data over the web, using my delphi thin clients. But i´would like to keep my server/service ...

How can I use exit codes to run shell scripts sequentially?

Since cruise control is full of bugs that have wasted my entire week, I have decided the existing shell scripts I have are simpler and thus better. Here is what I have so far svn update /var/www/...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...