PDA

View Full Version : QThread internal error while waiting for adopted threads: 87



lfiedler
2nd December 2010, 15:04
I'm occasionally seeing the above warning in my pyqt app. It looks like it's coming from the qthread watch dog. Any ideas? I don't specifically create any QThreads - just use regular python threads, gstreamer threads, and signal back to the gui thread. I typically see this when launching some QDialog's and then it stops when I close one or open another qdialog. Also, the error code 87 means ERROR_INVALID_PARAMETER ...

Qt watch dog code snippet where the warning is coming from:

void qt_adopted_thread_watcher_function(void *)
{
forever {
qt_adopted_thread_watcher_mutex.lock();

if (qt_adopted_thread_handles.count() == 1) {
qt_adopted_thread_watcher_handle = 0;
qt_adopted_thread_watcher_mutex.unlock();
break;
}

QVector<HANDLE> handlesCopy = qt_adopted_thread_handles;
qt_adopted_thread_watcher_mutex.unlock();

DWORD ret = WAIT_TIMEOUT;
int loops = (handlesCopy.count() / MAXIMUM_WAIT_OBJECTS) + 1, offset, count;
if (loops == 1) {
// no need to loop, no timeout
offset = 0;
count = handlesCopy.count();
ret = WaitForMultipleObjects(handlesCopy.count(), handlesCopy.constData(), false, INFINITE);
} else {
int loop = 0;
do {
offset = loop * MAXIMUM_WAIT_OBJECTS;
count = qMin(handlesCopy.count() - offset, MAXIMUM_WAIT_OBJECTS);
ret = WaitForMultipleObjects(count, handlesCopy.constData() + offset, false, 100);
loop = (loop + 1) % loops;
} while (ret == WAIT_TIMEOUT);
}

if (ret == WAIT_FAILED || !(ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + uint(count))) {
qWarning("QThread internal error while waiting for adopted threads: %d", int(GetLastError()));
continue;
}

const int handleIndex = offset + ret - WAIT_OBJECT_0;
if (handleIndex == 0){
// New handle to watch was added.
continue;
} else {
// printf("(qt) - qt_adopted_thread_watcher_function... called\n");
const int qthreadIndex = handleIndex - 1;
QThreadData::get2(qt_adopted_qthreads.at(qthreadIn dex))->deref();
CloseHandle(qt_adopted_thread_handles.at(handleInd ex));
QMutexLocker lock(&qt_adopted_thread_watcher_mutex);
qt_adopted_thread_handles.remove(handleIndex);
qt_adopted_qthreads.remove(qthreadIndex);
}
}
}

lfiedler
10th December 2010, 21:21
Anyone? Any ideas?

wysota
10th December 2010, 22:13
Try reproducing the problem with a simple example.

lkuoza
4th December 2013, 13:23
I have the same problem. It's a small bug in Qt. It won't make much trouble, but It's annoying. The problem ist hier:

int loops = (handlesCopy.count() / MAXIMUM_WAIT_OBJECTS) + 1, offset, count;
...
int loop = 0;
do {
offset = loop * MAXIMUM_WAIT_OBJECTS;
count = qMin(handlesCopy.count() - offset, MAXIMUM_WAIT_OBJECTS);
ret = WaitForMultipleObjects(count, handlesCopy.constData() + offset, false, 100);
loop = (loop + 1) % loops;
} while (ret == WAIT_TIMEOUT);


If handlesCopy.count() % MAXIMUM_WAIT_OBJECTS == 0, then the last call to WaitForMultipleObjects will have count == 0.

For example, if you habe 64 (== MAXIMUM_WAIT_OBJECTS) Threads, then loop will be 2. The first call will habe 64 handles. And the second one will habe 0 handles.

But see MSDN for WaitForMultipleObjects:

nCount [in]

The number of object handles in the array pointed to by lpHandles. The maximum number of object handles is MAXIMUM_WAIT_OBJECTS. This parameter cannot be zero.


The nCount CAN NOT BE ZERO. That is why you get this message.

The possible work around is not to call QThread::currentThread() in threads started not over QThread. Because in this case the adopted threads are used. In my case, I used Recursive QMutex. This also leads to calling QThreadData::current().

So in my case, I will just not use QMutex classe in non-QThread threads.

Why is this bug STILL OPEN AFTER 3 YEARS ???? :-(

The fix would be


int loops = (handlesCopy.count() / MAXIMUM_WAIT_OBJECTS), offset, count;
if ( (handlesCopy.count() % MAXIMUM_WAIT_OBJECTS) > 0 )
{
loops++
}