Solved Android dns resolve crash
-
@wantfat said in Android dns resolve crash:
QNetworkReply *reply = mgr->get(request);
Did you check that reply is a valid pointer?
-
@jsulm Yes, I tried it just now, but the same thing happened. I changed the code to
QMetaObject::invokeMethod(QAbstractEventDispatcher::instance(thr), ={
QTimer *t = new QTimer();
t->setSingleShot(true);
t->start(1);QObject::connect(t, &QTimer::timeout, [=](){ QHostInfo::lookupHost(QString("xyz%1.cn").arg(i), [=](const QHostInfo &info){ qDebug() << info.errorString(); QMetaObject::invokeMethod(t, "start"); }); }); });
It also crash in the same place.
-
@wantfat said in Android dns resolve crash:
I tried it just now, but the same thing happened
How? Please show the code.
"It also crash in the same place." - which place exactly?
-
@jsulm This is the code, I check reply valid
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "QAbstractEventDispatcher"
#include "QThread"
#include "QTimer"
#include "QNetworkAccessManager"
#include "QNetworkReply"
#include "QNetworkReply"
#include "QHostInfo"int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QGuiApplication app(argc, argv); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); for (int i = 0; i < 10; i++) { QThread *thr = new QThread(); thr->start(); while (!QAbstractEventDispatcher::instance(thr)) { thr->wait(1); } QMetaObject::invokeMethod(QAbstractEventDispatcher::instance(thr), [=](){ QTimer *t = new QTimer(); t->setSingleShot(true); t->start(1); QNetworkAccessManager *mgr = new QNetworkAccessManager(); QObject::connect(t, &QTimer::timeout, [=](){ QNetworkRequest request; request.setUrl(QString("http://xyz%1.cn").arg(i)); QNetworkReply *reply = mgr->get(request); if (reply == nullptr) { qDebug() << "reply is null"; return; } QObject::connect(reply, &QNetworkReply::finished, [=](){ reply->deleteLater(); t->start(); }); }); }); } return app.exec();
}
When it crash, The stack is as follows
1 dlfree 0xb6dcbf4c
2 free 0xb6db2258
3 __res_ndestroy 0xb6dba4da
4 __res_vinit 0xb6dba578
5 QHostInfoAgent::fromName(QString const&) 0xa2aadd7e
6 QHostInfoRunnable::run() 0xa2aa5516
7 QThreadPoolThread::run() 0xa2e6e05e
8 QThreadPrivate::start(void *) 0xa2e6c400
9 __pthread_start(void *) 0xb6db659c
10 __start_thread 0xb6db44c4
11 ?? -
Hi,
Why are you creating 10 threads making get requests almost as fast as possible all the time your application is running ?
On a side note, you are leaking QNetworkAccessManager and QTimer objects.
-
@sgaist If I had two threads, It would still crash, just for a long time. the request is serial execution .
thank you. -
I run on another phone (Android 9, armv7) , The code work well. The mobile phone that had abnormalities is Android 5.1 armv7. I am not sure whether it depend on mobile phone .
-
@wantfat you do realize that
QThread *thr = new QThread(); thr->start(); while (!QAbstractEventDispatcher::instance(thr)) { thr->wait(1); }
is doing nothing but delay forcefully delay the loop by 1 millisecond?
Also you don't need aQNetworkAccessManager
instance for each get request. QNetworkAccessManager can handle 5 get requests in parallel, IIRC, and the rest is automatically queued -
@j-hilk After call QThread::start the eventDispatcher of thread is null, so must take a sleep wait for eventDispatcher be create, QNetworkAccessManager only one instance for per thread .
-
@wantfat said in Android dns resolve crash:
, QNetworkAccessManager only one instance for per thread
no, from your code, you create 10 QNetworkAccessManager instances and all live inside the main(Gui) thread
-
-
@wantfat have you checked that ? by combining invokeMethod with a lambada the object reference pointer becomes a context pointer. I see no reason, why it should be called from the Thread instance, or I personally don't know, never tried threading in this unusual way.
-
@j-hilk Yes, I have checked it, this is detail info, https://stackoverflow.com/a/21653558
-
The test code work well on Qt 5.12.3, The problematic version is Qt 5.12.4 . I compared two versions of the relevant code
If method __res_init resolve fail dlsym be call, and it return a valid pointer, But it is not a thread safe function. Maybe so.
-
I solved this problem by export thread safe __res_init
#if (QT_VERSION == QT_VERSION_CHECK(5,12,4))
#include "resolv.h"
#include "QMutex"static QMutex mut;
int __res_init(void) {
QMutexLocker lck(&mut);
return res_init();
}#endif
Thanks every one.