PDA

View Full Version : Access violation while alt-tabbing from an actively updated plot widget



dumdidum
16th June 2009, 16:18
Hello,

I'm using Qt 4.5.1 and qwt 5.2.0 on Windows XP (Eclipse, g++). I have a graphing widget which inherits from QwtPlot. This is used to display often updated measurement data which is contained in a single curve. The graphing widget itself is refreshed with update() in the main thread using a timer, and the actual curve data is set from a measurement thread. Access to these functions is behind a single mutex. The plot also uses QwtPlotzoomer. The application seems to work fine when I don't disturb it while the plot is being updated, but I'm bumping to an access violation somewhat randomly if I alt-tab back on the application during a wrong time.

If I run the application under gdb, I also see the following warnings when I alt-tab in/out:


warning: QWidget::repaint: Recursive repaint detected

warning: QPainter::begin: Paint device returned engine == 0, type: 1

I have no repaint()s in the application itself, so they are performed somewhere within q(w)t. Also autoReplot is turned off.

The backtrace from Dr. Mingw is contained in the following post (character limit). gdb backtrace is not included due to some symbol-resolving problem.

dumdidum
16th June 2009, 16:19
meas.exe caused an Access Violation at location 1009a3a5 in module qwt5.dll Reading from location 09230028.

Registers:
eax=09230020 ebx=0022bc40 ecx=6a307128 edx=100afe38 esi=0000000a edi=0022c4dc
eip=1009a3a5 esp=0022b8d0 ebp=0022b8e8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202

Call stack:
AddrPC AddrReturn AddrFrame AddrStack Params
1009A3A5 100278BD 0022B8E8 0022B8D0 06A09EF8 0001068F 0022B908 10090B89
1009A3A5 qwt5.dll:1009A3A5 QVector<double>::operator[] qvector.h:333
...
template <typename T>
inline const T &QVector<T>::operator[](int i) const
> { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
return d->array[i]; }
template <typename T>
...

100278BD 10090B89 0022B8F8 0022B8D0 06A09EF0 0001068F 0022BA18 10034A59
100278BD qwt5.dll:100278BD QwtArrayData::y qwt_data.cpp:210
...
double QwtArrayData::y(size_t i) const
{
> return d_y[int(i)];
}

...

10090B89 10034A59 0022B908 0022B8D0 069F2850 0001068F 3F019EB8 000001D1
10090B89 qwt5.dll:10090B89E:\projects\meas\debug\qwt5.dll: No symbol found
_ZNK12QwtPlotCurve1yEi
10034A59 1003435D 0022BA18 0022B8D0 069F2850 0022BDE0 0022BCA0 0022BC40
10034A59 qwt5.dll:10034A59 QwtPlotCurve::drawLines qwt_plot_curve.cpp:815
...
{
int xi = xMap.transform(x(i));
> int yi = yMap.transform(y(i));

polyline.setPoint(i - from, xi, yi);
...

1003435D 10034230 0022BA48 0022B8D0 069F2850 0022BDE0 00000001 0022BCA0
1003435D qwt5.dll:1003435D QwtPlotCurve::drawCurve qwt_plot_curve.cpp:685
...
}
drawLines(painter, xMap, yMap, from, to);
> break;
case Sticks:
drawSticks(painter, xMap, yMap, from, to);
...

10034230 10033A03 0022BAD8 0022B8D0 069F2850 0022BDE0 0022BCA0 0022BC40
10034230 qwt5.dll:10034230 QwtPlotCurve::draw qwt_plot_curve.cpp:648
...

drawCurve(painter, d_data->style, xMap, yMap, from, to);
> painter->restore();

if (d_data->symbol->style() != QwtSymbol::NoSymbol)
...

10033A03 1002DF98 0022BAF8 0022B8D0 069F2850 0022BDE0 0022BCA0 0022BC40
10033A03 qwt5.dll:10033A03 QwtPlotCurve::draw qwt_plot_curve.cpp:521
...
{
draw(painter, xMap, yMap, 0, -1);
> }

/*!
...

1002DF98 1002DCD2 0022BB68 0022B8D0 069E7D40 0022BDE0 0022BC10 0022BC40
1002DF98 qwt5.dll:1002DF98 QwtPlot::drawItems qwt_plot.cpp:580
...
rect);

> painter->restore();
}
}
...

1002DCD2 10047690 0022BD18 0022B8D0 069E7D40 0022BDE0 C0000000 00000000
1002DCD2 qwt5.dll:1002DCD2 QwtPlot::drawCanvas qwt_plot.cpp:540
...
maps[axisId] = canvasMap(axisId);

> drawItems(painter,
d_data->canvas->contentsRect(), maps, QwtPlotPrintFilter());
}
...

10047690 1004728C 0022BE18 0022B8D0 069F2278 0022BF30 00000000 FFFFFFFF
10047690 qwt5.dll:10047690 QwtPlotCanvas::drawCanvas qwt_plot_canvas.cpp:337
...
((QwtPlot *)parent())->drawCanvas(&cachePainter);

> cachePainter.end();

painter->drawPixmap(contentsRect(), *d_data->cache);
...

1004728C 100470E5 0022BE88 0022B8D0 069F2278 0022BF30 00000001 0000004D
1004728C qwt5.dll:1004728C QwtPlotCanvas::drawContents qwt_plot_canvas.cpp:275
...
drawCanvas(painter);

> plot->setAutoReplot(doAutoReplot);
}

...

100470E5 00E3888D 0022BF58 0022B8D0 069F2278 0022C5F0 0022BFC8 00DEA420
100470E5 qwt5.dll:100470E5 QwtPlotCanvas::paintEvent qwt_plot_canvas.cpp:252
...
#endif

> if ( d_data->paintAttributes & PaintPacked )
setSystemBackground(false);
}
...

00E3888D 0127F743 0022C0C8 0022B8D0 069F2278 0022C5F0 00000000 00000001
00E3888D QtGuid4.dll:00E3888D
adjusting sections from 0x68f40000 to 0x00dc0000, 0x97e80000
E:\soft\Qt\4.5.1\bin\QtGuid4.dll: No symbol found
_ZN7QWidget5eventEP6QEvent
0127F743 00DD85CD 0022C0E8 0022B8D0 069F2278 0022C5F0 0022C5F0 05B14CC0
0127F743 QtGuid4.dll:0127F743E:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN6QFrame5eventEP6QEvent
00DD85CD 00DD8444 0022C118 0022B8D0 05B14DE8 069F2278 0022C5F0 7C9100B8
00DD85CD QtGuid4.dll:00DD85CDE:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN19QApplicationPrivate13notify_helperEP7QObjectP 6QEvent
00DD8444 6A242200 0022C468 0022B8D0 0022FDE0 069F2278 0022C5F0 00000312
00DD8444 QtGuid4.dll:00DD8444E:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN12QApplication6notifyEP7QObjectP6QEvent
6A242200 015BDF58 0022C508 0022B8D0 0022FDE0 069F2278 0022C5F0 0000004D
6A242200 QtCored4.dll:6A242200 QCoreApplication::notifyInternal qcoreapplication.cpp:610
...
bool returnValue;
try {
> returnValue = notify(receiver, event);
} catch(...) {
--threadData->loopLevel;
...

015BDF58 00E2FD10 0022C528 0022B8D0 069F2278 0022C5F0 0022C790 0000000C
015BDF58 QtGuid4.dll:015BDF58E:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN16QAccessibleEvent8setValueERK7QString
00E2FD10 00FF168A 0022C6C8 0022B8D0 069F2298 06A1C650 0022C8A0 0022C790
00E2FD10 QtGuid4.dll:00E2FD10E:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN14QWidgetPrivate10drawWidgetEP12QPaintDeviceRK7 QRegionRK6QPointiP8QPainterP19QWidgetBackingStore
00FF168A 00E2525E 0022C928 0022B8D0 06A0D128 0000000A 0022C958 01563590
00FF168A QtGuid4.dll:00FF168AE:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN14QWidgetPrivate10scrollRectERK5QRectii
00E2525E 00E38F79 0022C9A8 0022B8D0 05B185D0 6A2A51D4 6A302228 0022C9E0
00E2525E QtGuid4.dll:00E2525EE:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN14QWidgetPrivate16syncBackingStoreEv
00E38F79 012A62F0 0022CB18 0022B8D0 0022F250 06A095F0 00E040A9 00000000
00E38F79 QtGuid4.dll:00E38F79E:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN7QWidget5eventEP6QEvent
012A62F0 00DD85CD 0022CC08 0022B8D0 0022F250 06A095F0 06A095F0 05B14CC0
012A62F0 QtGuid4.dll:012A62F0E:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN11QMainWindow5eventEP6QEvent
00DD85CD 00DD8444 0022CC38 0022B8D0 05B14DE8 0022F250 06A095F0 6A2F7B69
00DD85CD QtGuid4.dll:00DD85CDE:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN19QApplicationPrivate13notify_helperEP7QObjectP 6QEvent
00DD8444 6A242200 0022CF88 0022B8D0 0022FDE0 0022F250 06A095F0 6A2B5729
00DD8444 QtGuid4.dll:00DD8444E:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN12QApplication6notifyEP7QObjectP6QEvent
6A242200 6A2B79FB 0022D028 0022B8D0 0022FDE0 0022F250 06A095F0 6A2B2CFC
6A242200 QtCored4.dll:6A242200 QCoreApplication::notifyInternal qcoreapplication.cpp:610
...
bool returnValue;
try {
> returnValue = notify(receiver, event);
} catch(...) {
--threadData->loopLevel;
...

6A2B79FB 6A24339B 0022D048 0022B8D0 0022F250 06A095F0 7FFDD000 0022D0EC
6A2B79FB QtCored4.dll:6A2B79FBE:\soft\Qt\4.5.1\bin\QtCored4 .dll: No symbol found
_ZN16QCoreApplication9sendEventEP7QObjectP6QEvent
6A24339B 6A2731BE 0022D148 0022B8D0 00000000 00000000 05B145F8 000000FF
6A24339B QtCored4.dll:6A24339B QCoreApplicationPrivate::sendPostedEvents qcoreapplication.cpp:1247
...
#else
try {
> QCoreApplication::sendEvent(r, e);
} catch (...) {
delete e;
...

6A2731BE 00E4715C 0022EFA8 0022B8D0 05B14C28 0022EFD0 05B145F8 6A17A207
6A2731BE QtCored4.dll:6A2731BE QEventDispatcherWin32::processEvents qeventdispatcher_win.cpp:681
...
QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);

> DWORD waitRet = 0;
HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
QVarLengthArray<MSG> processedTimers;
...

00E4715C 6A23F38E 0022EFE8 0022B8D0 05B14C28 0022F010 00000010 00000002
00E4715C QtGuid4.dll:00E4715CE:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_Z25qWinProcessConfigRequestsv
6A23F38E 6A23F510 0022F038 0022B8D0 0022F170 0022F0B0 00000020 6A25770E
6A23F38E QtCored4.dll:6A23F38E QEventLoop::processEvents qeventloop.cpp:149
...
if (flags & DeferredDeletion)
QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
> return d->threadData->eventDispatcher->processEvents(flags);
}

...

6A23F510 6A2428D1 0022F0E8 0022B8D0 0022F170 0022F150 00000000 00000000
6A23F510 QtCored4.dll:6A23F510 QEventLoop::exec qeventloop.cpp:200
...
try {
while (!d->exit)
> processEvents(flags | WaitForMoreEvents | EventLoopExec);
} catch (...) {
qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
...

6A2428D1 00DD6364 0022F1A8 0022B8D0 0022FDE0 00000001 0022FE08 0040F703
6A2428D1 QtCored4.dll:6A2428D1 QCoreApplication::exec qcoreapplication.cpp:888
...
self->d_func()->in_exec = true;
self->d_func()->aboutToQuitEmitted = false;
> int returnCode = eventLoop.exec();
threadData->quitNow = false;
if (self) {
...

00DD6364 0040F703 0022F1B8 0022B8D0 0022F250 0048B4C4 0022F264 00040501
00DD6364 QtGuid4.dll:00DD6364E:\soft\Qt\4.5.1\bin\QtGuid4.d ll: No symbol found
_ZN12QApplication4execEv
0040F703 00432FFD 0022FE08 0022B8D0 00000001 05B14DC0 05B14D38 0000000A
0040F703 meas.exe:0040F703 qMain main.cpp:30

dumdidum
16th June 2009, 16:43
Some possibly relevant code snippets:



void Graph::paintEvent(QPaintEvent *event) {

if (mutex.tryLock()) {
replot();
QwtPlot::paintEvent(event);

mutex.unlock();
}
}




Graph::Graph(QWidget *parent): QwtPlot(parent) {
mutex.lock();

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
timer->start(GRAPH_REDRAW_TIMER);

setCanvasBackground(QColor(29, 100, 141));
setFrameStyle(QFrame::NoFrame);
setLineWidth(0);
setCanvasLineWidth(2);
plotLayout()->setAlignCanvasToScales(true);

QwtPlotGrid *grid = new QwtPlotGrid;
grid->setMajPen(QPen(Qt::gray, 0, Qt::DashLine));
grid->setMinPen(QPen(Qt::gray, 0, Qt::DotLine));
grid->enableXMin(true);
grid->attach(this);

plotLayout()->setAlignCanvasToScales(true);

crv = new QwtPlotCurve();
crv->setPen(QColor(Qt::white));
crv->setStyle(QwtPlotCurve::Lines);
crv->attach(this);

zoomer = new QwtPlotZoomer(canvas(), true);
zoomer->setRubberBandPen(QPen(Qt::white, 2, Qt::DotLine));
zoomer->setTrackerPen(QPen(Qt::white));

connect(zoomer, SIGNAL(zoomed(const QwtDoubleRect &)),
this, SLOT(catchZoomed(const QwtDoubleRect &)));
//canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true);
zoomer->setZoomBase();

setAutoReplot(false);
mutex.unlock();
}




void Graph::refresh() {
mutex.lock();
// qDebug("refresh here");
update();
//replot();
mutex.unlock();
}




void Graph::catchZoomed(const QwtDoubleRect &rect) {
mutex.lock();
if (zoomer->zoomRectIndex() == 0) {
setAxisAutoScale(QwtPlot::yLeft);
setAxisAutoScale(QwtPlot::xBottom);
zoomer->setZoomBase();
}
mutex.unlock();
}

Uwe
17th June 2009, 06:06
Some possibly relevant code snippets:
The crash happens, when accessing the curve data. So the relevant code is how you assign the points to your curve.

Uwe

dumdidum
17th June 2009, 11:15
The crash happens, when accessing the curve data. So the relevant code is how you assign the points to your curve.

Uwe



void Graph::setXY(double *x, double *y, int size) {
mutex.lock();
crv->setData(x, y, size);
mutex.unlock();
}


The plot itself lives in the main thread, but this function is called from another thread.

dumdidum
17th June 2009, 14:01
Hurr, yeah. I get your hint now that I read the code and documents for a while: this is a threading problem. I replaced the direct function call from another thread with a signal-slot connection, which makes sure that the setData() call is handled in the appropriate thread.

Many thanks for your guidance!



Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread.