PDA

View Full Version : loading two sets of Qt binaries into the same process and moveToThread error



jauri
5th November 2012, 18:31
Thanks in advance for any help you can provide!! :)

When running my program in Debug mode on MacOSX 10.8.1 Qt 4.8 I get the following messages:

------

QObject::moveToThread: Current thread (0x101400f00) is not the object's thread (0x10b9f2ee0).
Cannot move to target thread (0x114b85c00)

On Mac OS X, you might be loading two sets of Qt binaries into the same process. Check that all plugins are compiled against the right Qt binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.

------

I am using multi-threaded programming, which may be part of the problem, but I can't sort out how the problems with 'moveToThread' relate to the problems with loading two sets of Qt binaries.

I am not using any pluggins, which appears to have been the problem in related threads:
http://www.qtcentre.org/threads/38206-Qt-4-7-Mac-OS-X-Might-be-loading-two-sets-of-Qt-binaries-into-the-same-process

-------

Threading:
I have a QObject holds a QList of QPointers to custom QGraphicsWidgets and then contains a function called 'process' that positions and sizes these custom widgets.

class VisBaseLayout : public QObject
{
Q_OBJECT
public:
VisBaseLayout(QObject *parent = 0);
VisBaseLayout(QList< QPointer< VisBaseElement > > elements, QObject *parent = 0);

void addElement( QPointer< VisBaseElement > e );
void addElements( QList< QPointer <VisBaseElement> > e );

signals:
void trackProgress(int stepsComplete);
void finished();
void error( QString err );

public slots:
virtual void process();

protected:
QList< QPointer < VisBaseElement > > elementsToLayout;

};

I create the layout in a manager object, and then call 'runLayout' to position the elements. The elements have been created in the main GUI thread, and no paint events are signaled in the layout object.

To run the layout I call:
void LayoutManager::runLayout()
{
QThread* thread = new QThread;
layout->moveToThread(thread);
connect(thread, SIGNAL(started()), layout, SLOT(process())); //once thread launched, begin processing
connect(layout, SIGNAL(finished()), thread, SLOT(quit()));//quit thread once layout is finished
connect(layout, SIGNAL(finished()), this, SLOT(callUpdate())); //once finsished, delete layout
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));//once finished, delete thread
thread->start();
}

This has been working, but I noticed the errors when I started calling this function again, in response to user changes in layout.

void LayoutManager::recomputeLayoutSlot()
{
runLayout();
}

-----------------
Loading 2 sets of Qt Binaries in the same process:


I followed instructions and set DYLD_PRINT_LIBRARIES=1 and I get a lengthy output of dylds, which I cannot post in full due to post-length restrictions. Here is a sample:

dyld: loaded: PathTo/build-desktop-Desktop_Qt_4_8_0_for_GCC__Qt_SDK__Debug/MyApp.app/Contents/MacOS/MyApp
dyld: loaded: PathTo/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtGui.framework/Versions/4/QtGui
dyld: loaded: PathTo/QtSDK/Desktop/Qt/4.8.0/gcc/lib/QtCore.framework/Versions/4/QtCore
dyld: loaded: /usr/lib/libstdc++.6.dylib
dyld: loaded: /usr/lib/libSystem.B.dylib
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon
dyld: loaded: /usr/lib/libz.1.dylib
dyld: loaded: /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
dyld: loaded: /usr/lib/libobjc.A.dylib
dyld: loaded: /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
dyld: loaded: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices
dyld: loaded: /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
dyld: loaded: /usr/lib/system/libcache.dylib
dyld: loaded: /usr/lib/system/libcommonCrypto.dylib
dyld: loaded: /usr/lib/system/libcompiler_rt.dylib
dyld: loaded: /usr/lib/system/libcopyfile.dylib
dyld: loaded: /usr/lib/system/libdispatch.dylib
dyld: loaded: /usr/lib/system/libdnsinfo.dylib
dyld: loaded: /usr/lib/system/libdyld.dylib
dyld: loaded: /usr/lib/system/libkeymgr.dylib
dyld: loaded: /usr/lib/system/liblaunch.dylib
dyld: loaded: /usr/lib/system/libmacho.dylib
dyld: loaded: /usr/lib/system/libquarantine.dylib
dyld: loaded: /usr/lib/system/libremovefile.dylib
dyld: loaded: /usr/lib/system/libsystem_blocks.dylib
dyld: loaded: /usr/lib/system/libsystem_c.dylib
dyld: loaded: /usr/lib/system/libsystem_dnssd.dylib
dyld: loaded: /usr/lib/system/libsystem_info.dylib
dyld: loaded: /usr/lib/system/libsystem_kernel.dylib
dyld: loaded: /usr/lib/system/libsystem_m.dylib
dyld: loaded: /usr/lib/system/libsystem_network.dylib
dyld: loaded: /usr/lib/system/libsystem_notify.dylib
dyld: loaded: /usr/lib/system/libsystem_sandbox.dylib
dyld: loaded: /usr/lib/system/libunc.dylib
dyld: loaded: /usr/lib/system/libunwind.dylib
dyld: loaded: /usr/lib/system/libxpc.dylib
dyld: loaded: /usr/lib/system/libcorecrypto.dylib
dyld: loaded: /usr/lib/libauto.dylib
dyld: loaded: /usr/lib/libc++abi.dylib
dyld: loaded: /usr/lib/libc++.1.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics
dyld: loaded: /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText
dyld: loaded: /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD
...... many more .......

amleto
6th November 2012, 00:20
We have a case of rtfm. The reason for your bolded troubles is all in the docs.
qobject.html#moveToThread

You cant 'movetothread' an object when the executing thread is not the same one that the object belongs to.

jauri
7th November 2012, 22:22
:mad:

I'm sorry, but this was a terribly unhelpful response. First of all: OF COURSE I READ THE DOCUMENTATION!!! I wouldn't post to this forum if I could have solved my problem with a simple Google search or a 1 paragraph description of the function associated with the error. Second of all: 'rtfm' is rude, condescending and unenlightening. I think most folks using this forum would prefer no response at all. Third of all: it is incredibly easy to write a short, polite response to a query such as this. Let me illustrate:

It looks like you are trying to 'movetothread' an object when the executing thread is not the same one that the object belongs to.
See the documentation on this function: http://doc.qt.nokia.com/latest/qobject.html#moveToThread
Does this answer your question?

Like that. Would that be so hard?

:mad:

-------

With that out of the way.....

I am not an expert at multi-threaded programming in Qt. So, let me assume that I could provide more information and ask more targeted questions about my problem.

I am using these approaches to multi-threaded programming:
http://www.developer.nokia.com/Community/Wiki/How_to_move_a_QObject_to_a_thread
and
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

I like these approaches because I can run custom objects (I'll call them: MyObject) in threaded and non-threaded mode, which suits my application quite well.

I create MyObject in the main thread. It is not instantiated with a parent. It is passed to another object 'MyContainer' and used to position QGraphicsElements in space. I store a pointer to MyObject in MyContainer. After instantiating MyObject, I pass it pointers to custom QGraphicsWidgets ('MyWidget'). MyObject stores these widgets in a QList. Then, I create the QThread and I move MyObject to this thread. From here I follow the template in the linked documents.

myObject->addElements(elements);
QThread* thread = new QThread;
myObject->moveToThread(thread);
connect(thread, SIGNAL(started()), myObject, SLOT(process())); //once thread launched, begin processing
connect(myObject, SIGNAL(finished()), thread, SLOT(quit()));//quit thread once layout is finished
connect(myObject, SIGNAL(finished()), myObject, SLOT(deleteLater())); //once finsished, delete layout
connect(myObject, SIGNAL(finished()), this, SLOT(callUpdate())); //once finsished, delete layout
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));//once finished, delete thread
thread->start();

One potential problem: Unlike the examples in the links above, I do not delete the myObject once the thread finishes, because I want to reuse it later.

So, here is one question:
What does it mean for an object to belong to a thread. Is it the thread it was instantiated in? Is it the thread that is running with pointers to that object? Is it the thread that is running with that object's parent?

Another question:
Perhaps the problem is that I try to store myObject, after moving it to a new thread. The new thread will get deleted ('deleteLater') and then perhaps myObject needs to be moved back to this thread to save it for later use? When I reuse it, I move it to a new thread again, so maybe this isn't the problem.

Other potential problems:
In 'MyObject' I store pointers to QGraphicsWidgets. I manipulate them using 'setGeometry' and 'setPos', which may have internal operations that only work in the main thread.
Also, it is possible that 'prepareGeometryChange' gets called when I manipulate these QGraphicsWidgets. I believe this may be illegal, and could easily be the source of my problem.

------

Thanks in advance for respectful responses. I really do appreciate the help! :)

wysota
7th November 2012, 23:58
One potential problem: Unlike the examples in the links above, I do not delete the myObject once the thread finishes, because I want to reuse it later.
Are you moving this object back to the originating thread before the worker thread dies?


What does it mean for an object to belong to a thread.
It means this thread is responsible for processing events belonging to this object.


Is it the thread it was instantiated in?
Initially yes.


Is it the thread that is running with pointers to that object?
A thread is just an execution context, so no.


Is it the thread that is running with that object's parent?
If an object has a parent, they both need to belong to the same thread, so yes.

It's all in the docs you claim to have read, you know...


When I reuse it, I move it to a new thread again, so maybe this isn't the problem.
The "so rude and totally unhelpful" response already contains the information you need. The docs (you claim to have read) clearly state that you can only push an object to a different thread from a thread the object has affinity to. So if you move an object from thread A (main thread) to thread B and then try to move the object from thread A (main thread) to thread C, it won't work, since only thread B can do that (regardless of what "thread affinity" would have meant).