PDA

View Full Version : non GUI thread use



fober
8th December 2010, 15:20
I make an unusual use of Qt: I've developped a Qt based library and I want to provide its services to Java too using a JNI (in addition to a standard C++ API).
Here is how it currently works:

when the library is initalized in the context of a stand-alone application, it creates a QGraphicsScene which is rendered in a QGraphicsView
when the library is initalized in a Java context, it creates a QGraphicsScene which is rendered in a QImage at Java client request

In both cases, I create a QApplication but in the Java context, I don't call QApplication::exec().
The QGraphicsScene is modified by the time task of a QTimer.
In the Java context, a QMutex ensures that the time task and the Java client request to get the scene bitmap data don't collide.

It basically works but it also crashes randomly and here is my current investigation state.
First of all, I've replaced the QPixmap with QImage since the final QImage rendering is made outside a GUI thread (and Qt complained about that).
Now there is a single remaining warning at client startup:
"QCoreApplication::sendPostedEvents: Cannot send posted events for objects in another thread"

Here is the code of the Java context rendering scheme:



QImage image (w, h, QImage::Format_ARGB32_Premultiplied);
QPainter painter(&image);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
fScene->render(&painter);
painter.end();

Note that it doesn't crash when I comment out the 'render' call.

I don't get anymore warning from Qt and the developer documentation only talks about QWidget that should not be used in a non GUI thread. Most of the crashes occur when modifying a QGraphicsSceneBspTreeIndex (or QGraphicsSceneBspTreeIndexPrivate) object. It looks like there are remaining unsafe operations called.

Any help would be greatly appreciated.

fober
9th December 2010, 17:23
I guess the question and the context are maybe not familiar to this list users.
If nobody has an answer, maybe someone knows a better place to ask.
Best,

wysota
9th December 2010, 18:52
I would rather say your post isn't clear at what you are really doing. A minimal compilable example reproducing the problem might help. And if not then even just a backtrace of the crash could be helpful.

fober
10th December 2010, 09:53
I would rather say your post isn't clear at what you are really doing. A minimal compilable example reproducing the problem might help. And if not then even just a backtrace of the crash could be helpful.

It's quite difficult to make a minimal compilable example since it involves a Qt based shared library, a JNI shared library and a Java virtual machine. I'll try to make one. Concerning the backtrace, here are two of them:

the first one corresponds to a timer task, i.e. it should not correspond to a JNI call

Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 QtGui 0x00000001354fbf82 QList<QGraphicsItem*>::detach_helper_grow(int, int) + 146
1 QtGui 0x000000013566a484 QGraphicsSceneInsertItemBspTreeVisitor::visit(QLis t<QGraphicsItem*>*) + 36
2 QtGui 0x0000000135668ab2 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 290
3 QtGui 0x0000000135668a13 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 131
4 QtGui 0x0000000135668ab2 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 290
5 QtGui 0x0000000135668a13 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 131
6 QtGui 0x0000000135668ab2 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 290
7 QtGui 0x0000000135668a13 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 131
8 QtGui 0x0000000135668ab2 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 290
9 QtGui 0x0000000135668a13 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 131
10 QtGui 0x0000000135668ab2 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 290
11 QtGui 0x0000000135668a13 QGraphicsSceneBspTree::climbTree(QGraphicsSceneBsp TreeVisitor*, QRectF const&, int) const + 131
12 QtGui 0x000000013566bde5 QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex( ) + 1013
13 QtGui 0x000000013566bef6 QGraphicsSceneBspTreeIndex::event(QEvent*) + 102
14 QtGui 0x0000000135081ddd QApplicationPrivate::notify_helper(QObject*, QEvent*) + 189
15 QtGui 0x0000000135088dfe QApplication::notify(QObject*, QEvent*) + 2094
16 QtCore 0x00000001322a2dec QCoreApplication::notifyInternal(QObject*, QEvent*) + 124
17 QtGui 0x0000000135081e7c qt_sendSpontaneousEvent(QObject*, QEvent*) + 44
18 QtGui 0x000000013503b79c QEventDispatcherMacPrivate::activateTimer(__CFRunL oopTimer*, void*) + 188
19 com.apple.CoreFoundation 0x00007fff86484be8 __CFRunLoopRun + 6488
20 com.apple.CoreFoundation 0x00007fff86482dbf CFRunLoopRunSpecific + 575
21 com.apple.HIToolbox 0x00007fff8611e91a RunCurrentEventLoopInMode + 333
22 com.apple.HIToolbox 0x00007fff8611e71f ReceiveNextEventCommon + 310
23 com.apple.HIToolbox 0x00007fff8611e5d8 BlockUntilNextEventMatchingListInMode + 59
24 com.apple.AppKit 0x00007fff870ebe64 _DPSNextEvent + 718
25 com.apple.AppKit 0x00007fff870eb7a9 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 155
26 com.apple.AppKit 0x00007fff870b148b -[NSApplication run] + 395
27 libawt.jnilib 0x000000011a940a04 +[AWTStarter startAWT:] + 1286
28 libawt.jnilib 0x000000011a904625 -[CPerformer perform] + 93
29 com.apple.Foundation 0x00007fff86d5344f __NSThreadPerformPerform + 219
30 com.apple.CoreFoundation 0x00007fff86485401 __CFRunLoopDoSources0 + 1361
31 com.apple.CoreFoundation 0x00007fff864835f9 __CFRunLoopRun + 873
32 com.apple.CoreFoundation 0x00007fff86482dbf CFRunLoopRunSpecific + 575


the second one clearly corresponds to a JNI call


Thread 28 Crashed: Java: AWT-EventQueue-0
0 libSystem.B.dylib 0x00007fffffe00f46 __memcpy + 1958
1 QtCore 0x0000000132a5fbbc QListData::remove(int) + 140
2 QtCore 0x0000000132a6011e QListData::erase(void**) + 46
3 QtGui 0x0000000135a95a9d QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex( ) + 173
4 QtGui 0x0000000135a95f1b QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCa che() + 27
5 QtGui 0x0000000135a962ff QGraphicsSceneBspTreeIndexPrivate::estimateItems(Q RectF const&, Qt::SortOrder, bool) + 271
6 QtGui 0x0000000135a963fb QGraphicsSceneBspTreeIndex::estimateTopLevelItems( QRectF const&, Qt::SortOrder) const + 27
7 QtGui 0x0000000135a9a17b QGraphicsSceneIndex::items(QRectF const&, Qt::ItemSelectionMode, Qt::SortOrder, QTransform const&) const + 315
8 QtGui 0x0000000135a709bf QGraphicsScene::items(QRectF const&, Qt::ItemSelectionMode) const + 111
9 QtGui 0x0000000135a893cf QGraphicsScene::render(QPainter*, QRectF const&, QRectF const&, Qt::AspectRatioMode) + 271
10 INScore 0x00000001315fba38 inscore::VSceneView::copy(unsigned int*, int, int, bool) + 280
11 INScore 0x000000013152e286 inscore::IGlue::getSceneView(unsigned int*, int, int, bool) + 294
12 INScore 0x0000000131608946 inscore::INScore::getScene(inscore::IGlue*, unsigned int*, int, int) + 22
13 libjniINScore.dylib 0x0000000117bfa613 Java_INScore_INScore_GetBitmap + 83
14 ??? 0x000000010301265b 0 + 4345374299
...
30 ??? 0x00000001030013eb 0 + 4345304043
31 libclient64.dylib 0x000000010109e249 JVM_Lseek + 185699
32 libclient64.dylib 0x000000010109e041 JVM_Lseek + 185179
33 libclient64.dylib 0x00000001010a8d2b JVM_StartThread + 2355
34 libclient64.dylib 0x00000001010a8c1e JVM_StartThread + 2086
35 libclient64.dylib 0x00000001010a8b89 JVM_StartThread + 1937
36 libclient64.dylib 0x00000001010a8a29 JVM_StartThread + 1585
37 libclient64.dylib 0x00000001010a88d3 JVM_StartThread + 1243
38 libclient64.dylib 0x000000010100cad2 JNI_CreateJavaVM_Impl + 46704
39 libSystem.B.dylib 0x00007fff859ed536 _pthread_start + 331
40 libSystem.B.dylib 0x00007fff859ed3e9 thread_start + 13

wysota
10th December 2010, 22:24
You have to explain clearly where the threads are. They are the most probable source of your problems.

fober
13th December 2010, 08:57
You're right but it's quite difficult since the threads are java VM threads and there are about thirty running.
Anyway and thanks to your previous advice (to make a minimal compilable example), I think I'm on the way to find the reason (and the solution). I need to make some more investigations but when I'll have the solution, I'll post it to this forum. Right now, it seems that the problem comes from the java side.