PDA

View Full Version : QGLWidget bug



Wizard
30th August 2007, 19:23
I think we have the bug in OpenGL texture engine. I’ve write application. It draws simple filled rectangle in separate thread, and then pushes image into main windows event loop through signal/slot system. Main widget requests thread to render new image every timer tick. After some time passed, it crashes deep into Qt core.

But, if you uncomment 2 lines in source code and compile/run it again, it will work perfectly! This lines changes inheritance to QWidget instead of QGLWidget.


//class OpenGLHashBug: public QWidget
class OpenGLHashBug: public QGLWidget
and

//OpenGLHashBug::OpenGLHashBug(QWidget *parent, Qt::WFlags flags): QWidget(parent)
OpenGLHashBug::OpenGLHashBug(QWidget *parent, Qt::WFlags flags): QGLWidget(parent)

I think bug is near synchronization of QHashMap for OpenGL textures...

What do you think about it? Is it my mistake or not? :confused:


P.S. Sorry for my bad English…

Wizard
30th August 2007, 19:26
Qt version: 4.3.1, compiled with Visual Studio 2005 SP1 under Vista x86-32, nv7800GTX video
I've just tested it on my notebook. Application crashes on XP SP2 + Qt 4.3.0 too...

jacek
30th August 2007, 21:57
I've let it running for 30 minutes on Linux with Qt 4.3.0 and it didn't crash. So it might be a windows-only problem.

Wizard
30th August 2007, 22:12
In Debug version or Release? I've found that Release version just randomly destroys heap and crashes when closing application... Debug version of Microsoft CRT marks freed memory by setting it by 0xfeeefeee, and I see access by this freed pointer.
You have tested it on multicore processor?
I haven't singlecore processors and couple of minutes is enough to crash the application...

jacek
30th August 2007, 23:26
In Debug version or Release?
Both.


I've found that Release version just randomly destroys heap and crashes when closing application...
Maybe Dr Watson/Dr Mingw will help to locate the method that tries to do that?


You have tested it on multicore processor?
Yes.

Wizard
30th August 2007, 23:40
Maybe Dr Watson/Dr Mingw will help to locate the method that tries to do that?
Yes.

I know that method )
Output:
First-chance exception at 0x67054768 (QtCored4.dll) in OpenGLHashBug.exe: 0xC0000005: Access violation reading location 0xfeeefeee.
Unhandled exception at 0x67054768 (QtCored4.dll) in OpenGLHashBug.exe: 0xC0000005: Access violation reading location 0xfeeefeee.

Call stack:
QtCored4.dll!QHashData::nextNode(QHashData::Node * node=0x0114d420) Line 203 + 0x3 bytes QtOpenGLd4.dll!QHash<QString,QCache<QString,QGLTexture>::Node>::const_iterator::operator++() Line 372 + 0xc bytes
QtOpenGLd4.dll!QHash<QString,QCache<QString,QGLTexture>::Node>::keys() Line 603
QtOpenGLd4.dll!QCache<QString,QGLTexture>::keys() Line 89 + 0x1f bytes
QtOpenGLd4.dll!qt_gl_clean_cache(const QString & cacheKey={...}) Line 1606 + 0xf bytes
QtOpenGLd4.dll!qt_gl_image_cleanup(__int64 key=0x0000005900000000) Line 1626 + 0x39 bytes
QtGuid4.dll!QImage::detach() Line 1303 + 0x10 bytes
QtGuid4.dll!QPainter::begin(QPaintDevice * pd=0x04edff2c) Line 1286
QtGuid4.dll!QPainter::QPainter(QPaintDevice * pd=0x04edff2c) Line 1056
OpenGLHashBug.exe!ImageRenderer::run() Line 81 + 0xd bytes
QtCored4.dll!QThreadPrivate::start(void * arg=0x01132770) Line 220
msvcr80d.dll!_callthreadstartex() Line 348 + 0xf bytes
msvcr80d.dll!_threadstartex(void * ptd=0x0114afd0) Line 331

Function in qhash.cpp:
...


QHashData::Node *QHashData::nextNode(Node *node)
{
union {
Node *next;
Node *e;
QHashData *d;
};
next = node->next;
Q_ASSERT_X(next, "QHash", "Iterating beyond end()");
if (next->next) // <<-- Error is here
return next;

int start = (node->h % d->numBuckets) + 1;
Node **bucket = d->buckets + start;
int n = d->numBuckets - start;
while (n--) {
if (*bucket != e)
return *bucket;
++bucket;
}
return e;
}

Sometimes I have another call stack:
QtCored4.dll!q_atomic_increment(volatile int * ptr=0xfeeefeee) Line 149 + 0xb bytes
QtCored4.dll!QBasicAtomic::ref() Line 73 + 0x10 bytes
QtCored4.dll!QString::QString(const QString & other={...}) Line 648 + 0x3e bytes
QtOpenGLd4.dll!QList<QString>::append(const QString & t={...}) Line 402 + 0xd bytes
QtOpenGLd4.dll!QHash<QString,QCache<QString,QGLTexture>::Node>::keys() Line 602
QtOpenGLd4.dll!QCache<QString,QGLTexture>::keys() Line 89 + 0x1f bytes
QtOpenGLd4.dll!qt_gl_clean_cache(const QString & cacheKey={...}) Line 1606 + 0xf bytes
QtOpenGLd4.dll!qt_gl_image_cleanup(__int64 key=0x0000010100000000) Line 1626 + 0x39 bytes
QtGuid4.dll!QImage::detach() Line 1303 + 0x10 bytes
QtGuid4.dll!QPainter::begin(QPaintDevice * pd=0x04faff2c) Line 1286
....

and another one exception in near that place:
First-chance exception at 0x67054768 (QtCored4.dll) in OpenGLHashBug.exe: 0xC0000005: Access violation reading location 0x00000001. // <<-- Access in freed pointer (0x00000000) + 1, e.g. freed object/structure.
Call stack:
QHashData::nextNode(QHashData::Node * node=0x01c36a28) Line 203 + 0x3 bytes
QHash<QString,QCache<QString,QGLTexture>::Node>::const_iterator::operator++() Line 372 + 0xc bytes
QHash<QString,QCache<QString,QGLTexture>::Node>::keys() Line 603
QCache<QString,QGLTexture>::keys() Line 89 + 0x1f bytes
qt_gl_clean_cache(const QString & cacheKey={...}) Line 1606 + 0xf bytes
qt_gl_image_cleanup(__int64 key=0x000002f600000000) Line 1626 + 0x39 bytes
QImage::detach() Line 1303 + 0x10 bytes
QPainter::begin(QPaintDevice * pd=0x0500ff2c) Line 1286
QPainter::QPainter(QPaintDevice * pd=0x0500ff2c) Line 1056
ImageRenderer::run() Line 81 + 0xd bytes
QThreadPrivate::start(void * arg=0x01c02770) Line 220

That's why is think that Image::detach() method is not protected by mutex

Wizard
31st August 2007, 00:32
I have installed openSUSE in VMWare with Qt 4.3.1. First time I think that there was no bugs... But if you will drag, resize, click, move mouse (use application) you will have segmentation fault error...
I've changed source in that way.

startTimer(0);

Call stack:
11 QHashData::nextNode() /home/wizard/qt-x11-opensource-src-4.3.1/src/corelib/tools/qhash.cpp:220 0xb735bbad
10 QHash<QString, QCache<QString, QGLTexture>::Node>::keys() /home/wizard/qt-x11-opensource-src-4.3.1/src/corelib/tools/qhash.h:389 0xb7ed8102
9 qt_gl_clean_cache() /home/wizard/qt-x11-opensource-src-4.3.1/src/corelib/tools/qcache.h:106 0xb7ed69f5
8 qt_gl_image_cleanup() /home/wizard/qt-x11-opensource-src-4.3.1/src/opengl/qgl.cpp:1643 0xb7ed6c7b
7 QImage::detach() /home/wizard/qt-x11-opensource-src-4.3.1/src/gui/image/qimage.cpp:1320 0xb788f144
6 QPainter::begin() /home/wizard/qt-x11-opensource-src-4.3.1/src/gui/painting/qpainter.cpp:1301 0xb78daeff
5 QPainter() /home/wizard/qt-x11-opensource-src-4.3.1/src/gui/painting/qpainter.cpp:1072 0xb78ddfb5
4 ImageRenderer::run() /home/wizard/workspace/GLTest/gltest.cpp:70 0x0804abfa
3 QThreadPrivate::start() /home/wizard/qt-x11-opensource-src-4.3.1/src/corelib/thread/qthread_unix.cpp:181 0xb7342c62
2 start_thread() 0xb7166112
1 clone() 0xb6fdb2ee



if (next->next) // <<-- Segmentation fault
return next;


P.S. It is difficult to explain what I mean )) I badly know english, online translators works very-very-very bad... Try to understand ) Together we will find solution!

jacek
31st August 2007, 01:15
I have installed openSUSE in VMWare with Qt 4.3.1. First time I think that there was no bugs... But if you will drag, resize, click, move mouse (use application) you will have segmentation fault error...
I've tried resizing, clicking and moving the window, but it didn't crash.


QImage::detach() /home/wizard/qt-x11-opensource-src-4.3.1/src/gui/image/qimage.cpp:1320 0xb788f144
6 QPainter::begin() /home/wizard/qt-x11-opensource-src-4.3.1/src/gui/painting/qpainter.cpp:1301 0xb78daeff
Hmm... these two methods are always present in the backtrace. What happens if you change the code this way:
painter.fillRect(0, 0, 50, 50, QColor(qrand()));
painter.end(); // <-------

emit ImageReady(MyImage);
?

Wizard
31st August 2007, 01:26
What happens if you change the code this way:
painter.fillRect(0, 0, 50, 50, QColor(qrand()));
painter.end(); // <-------

emit ImageReady(MyImage);
?
The same bug. First, QPainter::end() was called automatically. Second, bug is near OpenGL, because after changing inheritance to QWidget all works...

spud
31st August 2007, 09:32
This looks like a bug to me.
It seems qt_gl_clean_cache() isn't reentrant since it accessess the
static QGLTextureCache *qt_tex_cache(qgl.cpp) without trying to protect it with a mutex. They don't even use the QGLOBALSTATIC macro. You should submit a bug report.

Wizard
31st August 2007, 11:07
May be they don't use it for performance reasons? I send bug report to Trolltech...
Thanks for advice )

Wizard
31st August 2007, 12:23
I've designed some workaround for this bug ) Just half an hour was enough... :cool: