Прерывание потока во время выполнения
От: andrey-x86  
Дата: 10.06.13 13:08
Оценка:
Добрый день, коллеги.
Занимаюсь модификацией кода приложения на Qt, и столкнулся с непредвиденным для меня поведением. Есть наследник класса QThread, который в методе run() выполняет полезную работу время от времени. Объект также подписан слотом handleSuccess() на сигнал от объекта из другого потока, который принимает асинхронные ответы с сервера по HTTP. В моем понимании, слот не должен вызываться посреди контекста потока, пока поток не войдет в цикл обработки сообщений. Однако, по какой-то причине это происходит. Далее код.

Класс WorkerThread -- выполняется как поток:

class WorkerThread : public QObject {
    Q_OBJECT
public:
    WorkerThread() { moveToThread(this); /* дальнейшая инициализация */ }
    void run();
    void foo();
    
public slots:
    void handleSuccess(const QByteArray &);
    
private:
    QMutex mutex;
    MyResource resource;
    
/* ... другие объявления */
};

void WorkerThread::foo() {
    QMutexLocker locker(&mutex);
    /* Единоличная работа с защищаемым ресурсом */
}

void WorkerThread::run() {
    QEventLoop signalWaiterEventLoop;
    connect(this, SIGNAL(terminated()), &signalWaiterEventLoop, SLOT(quit()), Qt::QueuedConnection);
    connect(this, SIGNAL(shutdownThread()), &signalWaiterEventLoop, SLOT(quit()), Qt::QueuedConnection);
    connect(this, SIGNAL(dbChanged()), &signalWaiterEventLoop, SLOT(quit()), Qt::QueuedConnection);

    while (!mShutdown) {
        signalWaiterEventLoop.exec();
        if (mShutdown) break;
        /* ... полезная нагрузка */
        foo();
        /* ... полезная нагрузка */
    }
}


void WorkerThread::handleSuccess(const QByteArray & data) {
    QMutexLocker locker(&mutex);
    /* обработка данных */
}


Объект создается и инициализируется в главном потоке приложения:

void SomeClass::init() {
    /* ... */
    mWorker = new WorkerThread();
    connect(connect(mProtocol, SIGNAL(dataReceived(QByteArray)), mWorker, SLOT(processSuccess(QByteArray)),
                Qt::QueuedConnection));    
    mWorker->start();
    /* ... */
}


Ошибка возникает, когда метод foo() вызывается в run(), захватывает мьютекс, а затем выполнение прерывается методом handleSuccess() безо всяких видимых причин (логирование перед emit-ом сигнала dataReceived ничего не дает: в логах log4qt запись не появляется). Когда handleSuccess() захватывает мьютекс, программа получает дедлок.

Таким образом, возникает вопрос: что я делаю не так, либо чего я не учитываю?
c++ qt threading
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.