PDA

View Full Version : Qt warning of type conversion already registered



nyaruko
9th November 2014, 19:44
I have a multi-thread Qt program where the Qt sometimes give a warning:


Type conversion already registered from type QPair<QByteArray,QByteArray> to type QtMetaTypePrivate::QPairVariantInterfaceImpl
I have found the warning is from this Qt’s function:


bool QMetaType::registerConverterFunction(QtPrivate::Ab stractConverterFunction *f, int from, int to)
{
if (!customTypesConversionRegistry()->insertIfNotContains(from, to, f)) {
qWarning("Type conversion already registered from type %s to type %s",
QMetaType::typeName(from), QMetaType::typeName(to));
if (f)
f->destroy(f);
return false;
}
return true;
}
I have checked my own code, nobody is calling this function, so it must be inside Qt’s own function. Could any one give me a hint what’s causing this issue or which function actually called the above function inside Qt’s code. I am using Qt 5.3.2. I wonder whether this could be a Qt’s bug instead of mine?

ChrisW67
9th November 2014, 21:28
Does your code ever call qRegisterMetatype() or use Q_DECLARE_METATYPE()?

nyaruko
10th November 2014, 06:23
Does your code ever call qRegisterMetatype() or use Q_DECLARE_METATYPE()?

Yes. I did call them. And there are also a bunch of calling inside the generated moc_ file. Could you give more hints?

Since I dont think I have ever touched the type conversion between QPair<QByteArray,QByteArray> to type QtMetaTypePrivate::QPairVariantInterfaceImpl...

ChrisW67
10th November 2014, 21:08
Those Calls in your code are the most likely triggers for the message you are seeing. If it really bothers you, try to work out which of your calls (not the ui generated code) to the metatype functions triggers the message. It is possible you get that message regardless of what your types are, or that you have types that equate to byte arrays internally.

nyaruko
11th November 2014, 14:30
Those Calls in your code are the most likely triggers for the message you are seeing. If it really bothers you, try to work out which of your calls (not the ui generated code) to the metatype functions triggers the message. It is possible you get that message regardless of what your types are, or that you have types that equate to byte arrays internally.
Hi, it seems if I just comment this
QNetworkAccessManager network; from my code, that warning just won't come out anymore.
What could be the reason???

wysota
12th November 2014, 13:42
Where do you have that line in your code? Is it a class member variable, a local variable, a global one?

don@thegagnes.com
2nd December 2014, 21:29
It's in a class member variable. The qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >(); call inside the QNetworkAccessManager constructor is failing. Working on getting it to repro in the debugger. It smells like a thread safety issue with qRegisterMetaType, but just guessing at this point.

wysota
2nd December 2014, 21:42
Where do you have threads in your code? How do you use them?

don@thegagnes.com
2nd December 2014, 22:26
think it's just a race condition associated with getting the qWarning message. In this code:

template <typename T>
inline bool QtPrivate::IsMetaTypePair<T, true>::registerConverter(int id)
{
const int toId = qMetaTypeId<QtMetaTypePrivate::QPairVariantInterfaceImpl>();
if (!QMetaType::hasRegisteredConverterFunction(id, toId)) {
QtMetaTypePrivate::QPairVariantInterfaceConvertFun ctor<T> o;
static const QtPrivate::ConverterFunctor<T,
QtMetaTypePrivate::QPairVariantInterfaceImpl,
QtMetaTypePrivate::QPairVariantInterfaceConvertFun ctor<T> > f(o);
return QMetaType::registerConverterFunction(&f, id, toId);
}
return true;
}

If you hit it with two threads at the same time both can get false from QMetaType::hasRegisteredConverterFunction(id, toId). Then the first one that wins registers the converter and the second gets a qWarning about the converter already being registered message. Nothing bad happens unless you are running your code with QT_FATAL_WARNINGS during automated testing which we do. And because of that this comes out as a bug on our side when it really isn't.

wysota
2nd December 2014, 22:58
If you hit it with two threads at the same time

Do you hit it with two threads at the same time? Where do these threads come in your code?

don@thegagnes.com
3rd December 2014, 18:44
I haven't been able to catch this one in a debugger yet. It is very intermittent. It tends to get hit by automation which is difficult to hook into. I can make it go away by calling qRegisterMetatype on QPair<QByteArray,QByteArray> once right at the start of the app.

wysota
3rd December 2014, 19:15
Look, I am asking a very simple question -- "where do you have threads in your code?". And another one -- "how is the code of these threads related to instantiating QNetworkAccessManager?". Please answer them without mentioning "qRegisterMetaType" or "debugger".

don@thegagnes.com
3rd December 2014, 19:28
QNetworkAccessManager is used on the main thread and also in threads which are used to query map contents from Google and Bing map servers. Both of these threads are started at boot time. Boot time is also when the problem occurs.

wysota
4th December 2014, 08:30
Do you really need that many instances of QNAM? A secondary question would be if you need threads at all as a single QNAM instance can handle multiple requests simultaneously.

musicullum
11th May 2015, 17:47
Do you really need that many instances of QNAM? A secondary question would be if you need threads at all as a single QNAM instance can handle multiple requests simultaneously.
I have the same issue. It's obviously a race condition during initialisation.
I address two servers with different IP adresses in different threads with different priorities and different needs (one performs synchronous and the other async backgroud tasks), so using the same QNAM is not an option I guess.
It's probably no big deal, will try to register the metatype beforehand as don suggested. Just ignoring the warning is not sufficient as it crashes soon. I also wonder in general if not the registerMetaType operation should be protected against such race conditions?

ChrisW67
11th May 2015, 23:28
qRegisterMetatype() is specifically documented as thread-safe so it should already be serialising competing accesses as required. A small, self-contained example that reproduces the problem would be useful. That will eliminate thread-related curiosities in your code as much as demonstrate them in Qt.

musicullum
12th May 2015, 11:50
qRegisterMetatype() is specifically documented as thread-safe so it should already be serialising competing accesses as required. A small, self-contained example that reproduces the problem would be useful. That will eliminate thread-related curiosities in your code as much as demonstrate them in Qt.

qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >();
Insert before creating any QNAM and the problem vanishes.
Providing an example is tricky, as the race condition only happens occasionally. Create and start two or more threads with different priorities (probably lower first, which then gets pre-empted by the second with higher priority), each of which creates a QNAM in its run () method. That should reveal the problem if the timing is "right".