Почему невозможно дождаться завершения процесса Qt в статическом деструкторе?

следующий фрагмент кода запускает процесс, который занимает одну секунду, чтобы закончить, а затем ждет завершения этого процесса перед выходом. По какой-то причине, следующий код зависает в p->waitForFinished() несмотря на то, что процесс закончился.

#include <QtCore/QProcess>    

class A
{
  public:
    A():
        p(0)
    {
    }

    ~A()
    {
        p->waitForFinished();
        delete p;
    }

    void start()
    {
        p = new QProcess(0);
        p->start("sleep 1");
    }

    QProcess *p;
};

int main(void)
{
  static A a;
  a.start();

  return 0;
}

однако, как только a не объявляется статически, а следующим образом:

A a;

на waitForFinished() вызов завершается успешно. Это ошибка Qt, или это ожидаемое поведение? Я подозреваю, что требуется какая-то логика. чтобы определить, успешно ли приложение завершено, уже уничтожено после того, как деструктор A называется.

1 ответов


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

вы отсоединили нить, вернувшись из main (который завершает все потоки в процессе, отсоединяя их, если они соединяемы).

и вы очистили QProcess поток, присоединившись к нему через waitForFinished.

вы можете отсоединить нить или присоединиться к ней, но вы не можете сделать оба, даже косвенно. По-видимому, отряд выигрывает, и соединение зависает.

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

как правило, потоки не должны создаваться в конструкторах или очищаться в деструкторах. Это в первую очередь за время этих операций требует более четкого контроля, чем это возможно. И они никогда не должны быть созданы до main запускается и не очищается после main -- возвращается снова, потому что вам нужно контролировать контекст, в котором эти вещи происходят.