PDA

View Full Version : A crash in QGraphicsScenePrivate::draw()



platon
10th October 2012, 07:31
Did somebody encountered such kind of crash:


Thread 1 (LWP 1380):
#0 0x740b70c4 in raise () from /home/work/Projects/unistack/repository/unistack-output/pil_packages/p-broadcomnexus-bcm7428/staging_dir/lib/libc.so.0
#1 0x740b0754 in abort () from /home/work/Projects/unistack/repository/unistack-output/pil_packages/p-broadcomnexus-bcm7428/staging_dir/lib/libc.so.0
#2 0x742b9f8c in signal_handler () from /home/work/Projects/unistack/repository/unistack-output/pil_packages/p-broadcomnexus-bcm7428/staging_dir/usr/lib/libdirect-1.4.so.15
#3 <signal handler called>
#4 0x75db7edc in QGraphicsScenePrivate::draw(QGraphicsItem*, QPainter*, QTransform const*, QTransform const*, QRegion*, QWidget*, float, QTransform const*, bool, bool) ()
#5 0x75db9db8 in QGraphicsScenePrivate::drawSubtreeRecursive(QGraph icsItem*, QPainter*, QTransform const*, QRegion*, QWidget*, float, QTransform const*) ()
#6 0x75db7ed4 in QGraphicsScenePrivate::draw(QGraphicsItem*, QPainter*, QTransform const*, QTransform const*, QRegion*, QWidget*, float, QTransform const*, bool, bool) ()
#7 0x75db9db8 in QGraphicsScenePrivate::drawSubtreeRecursive(QGraph icsItem*, QPainter*, QTransform const*, QRegion*, QWidget*, float, QTransform const*) ()
#8 0x75db7ed4 in QGraphicsScenePrivate::draw(QGraphicsItem*, QPainter*, QTransform const*, QTransform const*, QRegion*, QWidget*, float, QTransform const*, bool, bool) ()
#9 0x75db9db8 in QGraphicsScenePrivate::drawSubtreeRecursive(QGraph icsItem*, QPainter*, QTransform const*, QRegion*, QWidget*, float, QTransform const*) ()
#10 0x75db7ed4 in QGraphicsScenePrivate::draw(QGraphicsItem*, QPainter*, QTransform const*, QTransform const*, QRegion*, QWidget*, float, QTransform const*, bool, bool) ()
#11 0x75db9db8 in QGraphicsScenePrivate::drawSubtreeRecursive(QGraph icsItem*, QPainter*, QTransform const*, QRegion*, QWidget*, float, QTransform const*) ()
#12 0x75db7ed4 in QGraphicsScenePrivate::draw(QGraphicsItem*, QPainter*, QTransform const*, QTransform const*, QRegion*, QWidget*, float, QTransform const*, bool, bool) ()
#13 0x75db9db8 in QGraphicsScenePrivate::drawSubtreeRecursive(QGraph icsItem*, QPainter*, QTransform const*, QRegion*, QWidget*, float, QTransform const*) ()
#14 0x75db7ed4 in QGraphicsScenePrivate::draw(QGraphicsItem*, QPainter*, QTransform const*, QTransform const*, QRegion*, QWidget*, float, QTransform const*, bool, bool) ()
#15 0x75db9db8 in QGraphicsScenePrivate::drawSubtreeRecursive(QGraph icsItem*, QPainter*, QTransform const*, QRegion*, QWidget*, float, QTransform const*) ()
#16 0x75db7ed4 in QGraphicsScenePrivate::draw(QGraphicsItem*, QPainter*, QTransform const*, QTransform const*, QRegion*, QWidget*, float, QTransform const*, bool, bool) ()
#17 0x75db9db8 in QGraphicsScenePrivate::drawSubtreeRecursive(QGraph icsItem*, QPainter*, QTransform const*, QRegion*, QWidget*, float, QTransform const*) ()
#18 0x75dba5e8 in QGraphicsScenePrivate::drawItems(QPainter*, QTransform const*, QRegion*, QWidget*) ()
#19 0x75ddb8fc in QGraphicsView::paintEvent(QPaintEvent*) ()
#20 0x7584f220 in QWidget::event(QEvent*) () from /home/work/Projects/unistack/repository/unistack-output/pil_packages/p-broadcomnexus-bcm7428/staging_dir/usr/lib/libQtGui.so.4
#21 0x75bd0da8 in QFrame::event(QEvent*) () from /home/work/Projects/unistack/repository/unistack-output/pil_packages/p-broadcomnexus-bcm7428/staging_dir/usr/lib/libQtGui.so.4
#22 0x75ddda24 in QGraphicsView::viewportEvent(QEvent*) ()

It seems the crash happens when webkit for some reason removes QGraphicsItem in GraphicsLayerQtImpl::~GraphicsLayerQtImpl() while this item is being drawn in QGraphicsScenePrivate::draw().

wysota
10th October 2012, 08:28
Show your code.

platon
10th October 2012, 11:33
I'm just using QGraphicsWebView for rendering web content


class WebView : public QGraphicsWebView



WebView *Application::newBrowserWindow()
{
WebView *browser = new WebView();
browser->setGeometry( geometry );
scene->addItem( browser );
browser->show();
return browser;
}



WebView *view = newBrowserWindow();
view->load( uri );

wysota
10th October 2012, 11:38
Is that the whole code needed to reproduce the problem?

platon
10th October 2012, 15:51
No, but the main actions are in this code.
The whole code is executed on embedded system and Qt draws using DirectFB plugin. So I believe it's hard to reproduce it on your side.

Today I found out that the crash disappears when I disable QWebSettings::AcceleratedCompositingEnabled option.
Before while digging in Qt code I notices that the place of code which caused the crash was under #if USE(ACCELERATED_COMPOSITING) define.
It seems this option enables some sophisticated drawing algorithms with caching.

I suppose this crash is some synchronization issue because it happens after some particular page is rendered n times (it may be 5th or 20th time).

As I said previously I managed to find the situation after which crash happens.
I added custom property to QGraphicsItem. I set it when the program enters QGraphicsScenePrivate::draw(QGraphicsItem *item, ...) and reset when the program leaves this method.
I check this property in GraphicsLayerQtImpl::~GraphicsLayerQtImpl(). When the property is set (item is being drawn) the crash happens.

wysota
10th October 2012, 16:13
What do you need this property for?

platon
10th October 2012, 16:24
Only for testing. Just to detect the situation when the crash happens.
Actually not a property but just custom data set by QGraphicsItem::setData(). it seemed to me a good approach.

wysota
10th October 2012, 18:11
What you experience is not really a crash, you can see there is some UNIX signal emitted that causes libdirect to abort. I would assume your framebuffer implementation is incomplete and indeed some optimised code path causes it to malfunction.

Or you are using threads incorrectly... Do you have multiple threads in your app?

platon
11th October 2012, 07:39
What you experience is not really a crash, you can see there is some UNIX signal emitted that causes libdirect to abort.
I called it a crash because the signal is SEGFAULT:


(!) [ 1389: 1349881576.870] --> Caught signal 11 (at 0x40, invalid address) <--


I would assume your framebuffer implementation is incomplete and indeed some optimised code path causes it to malfunction.
Yes, this seems to be true.

Or you are using threads incorrectly... Do you have multiple threads in your app?
In core dump I can see only a single browser thread... Nevertheless I will double check the code to be sure.
Thanks for your hints.

platon
17th October 2012, 09:04
Finally I came to the following solution (workaround):


--- RenderLayer.cpp.org>2011-12-08 07:06:03.000000000 +0200
+++ RenderLayer.cpp>2012-10-16 17:03:18.313964345 +0300
@@ -3874,7 +3874,7 @@
#if USE(ACCELERATED_COMPOSITING)
if (compositor()->inCompositingMode()) {
if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty)
- compositor()->updateCompositingLayers(CompositingUpdateOnPaiting OrHitTest, this);
+// compositor()->updateCompositingLayers(CompositingUpdateOnPaiting OrHitTest, this);
return;
}
#endif