PDA

View Full Version : Windows CE genenerates QThread internal error while waiting for adopted threads error



ncsunickv
5th January 2012, 14:58
Hi,

Under Windows CE6 R3/Embedded Compact 7, QT 4.7.3, built against the Windows Mobile Professional 6 SDK, the following error message is displayed under two different conditions:

QThread internal error while waiting for adopted threads error: 6

The error code here appears to indicate the thread code is referencing an invalid handle.

First scenario:

This code is taken from an online example for capturing and playing audio

void DlgVolumeSettings::onPlayClicked(void)
{
qDebug("onPlayClicked\r");
inputFile.setFileName(RAW_AUDIO_FILENAME);
inputFile.open(QIODevice::ReadOnly);

QAudioFormat format;
// Set up the format, eg.
format.setFrequency(8000);
format.setChannels(1);
format.setSampleSize(8);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
qWarning()<<"raw audio format not supported by backend, cannot play audio.";
return;
}

audioOut = new QAudioOutput(format, this);
connect(audioOut,SIGNAL(stateChanged(QAudio::State )),SLOT(finishedPlaying(QAudio::State)));
audioOut->start(&inputFile);
}

void DlgVolumeSettings::finishedPlaying(QAudio::State state)
{
qDebug("finishedPlaying\r");
if(state == QAudio::IdleState)
{
audioOut->stop();
inputFile.close();
delete(audioOut);
}
}

Here, as soon as audioOut->Start is called, these messages are observed.


Scenario 2:

A class is used to make a call into a DLL. During this call, it passes pointers to the DLL to it's own static methods, which are used as callbacks from the DLL. Upon the DLL calling these callbacks, this same error message is generated. Here is the QT code being invoked:

From qthread_win.cpp

/*! \internal
This function loops and waits for native adopted threads to finish.
When this happens it derefs the QThreadData for the adopted thread
to make sure it gets cleaned up properly.
*/
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();
#if !defined(Q_OS_WINCE) || (defined(_WIN32_WCE) && (_WIN32_WCE>=0x600))
CloseHandle(qt_adopted_thread_handles.at(handleInd ex));
#endif
QMutexLocker lock(&qt_adopted_thread_watcher_mutex);
qt_adopted_thread_handles.remove(handleIndex);
qt_adopted_qthreads.remove(qthreadIndex);
}
}
}

It's not clear to me if and how to implement a work-around for these scenarios. Under the same conditions for a Windows desktop build, these warning messages are not generated. Thanks,

Nick

ncsunickv
5th January 2012, 17:36
Some additional info. It appears that 4.7.3/4.7.4 are similar in the core thread code, however, diffing 4.8.0 shows some changes that MAY address this issue. Unfortunately, 4.8.0 fails with build issues against the Windows Mobile 6 Professional SDK. We will be operating with a commercial licence at some point, so modifying the core code is not an option for us currently, in order to resolve these build issues. Thanks,

Nick

lkuoza
4th December 2013, 12:52
I habe 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.

Added after 34 minutes:

The fix would be


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

Collen414
14th December 2013, 10:11
I like it a lot. You know precisely what your talking about exactly where other people are coming from on this issue.

Collen414
29th April 2014, 16:20
applied this and it works. thank you guys to share with us