My app queues a series of files to download, and downloads each one in sequence. That is, it calls QNetworkAccessManager::get(), checks for errors in onFinished(), and if there are none, saves the data to disk. There are problems with this overall approach -- as opposed to writing the data as it arrives -- in that if a given file is too large, it will fill up the memory on a mobile device and cause the OS to kill the app.
That's not what I am seeing here.
And in fact, I am only seeing this for a particular file on a particular device, which happens to be a Nexus 7 running Android 5.1. Works fine on every iOS device I've tried, and a Nexus 7 running Android 6.0.1. The file downloads just fine, and there are no errors. But when I try to call readAll() on my non-null instance of QNetworkReply:
F/libc (23481): Fatal signal 6 (SIGABRT), code -6 in tid 23524 (QtThread)
I/DEBUG ( 182): pid: 23481, tid: 23524, name: QtThread >>> my.org.appname <<<
E/lowmemorykiller( 176): Error writing /proc/23481/oom_score_adj; errno=22
I/Zygote ( 195): Process 23481 exited due to signal (6)
I/ActivityManager( 543): Process my.org.appname (pid 23481) has died
F/libc (23481): Fatal signal 6 (SIGABRT), code -6 in tid 23524 (QtThread)
I/DEBUG ( 182): pid: 23481, tid: 23524, name: QtThread >>> my.org.appname <<<
E/lowmemorykiller( 176): Error writing /proc/23481/oom_score_adj; errno=22
I/Zygote ( 195): Process 23481 exited due to signal (6)
I/ActivityManager( 543): Process my.org.appname (pid 23481) has died
To copy to clipboard, switch view to plain text mode
Similar topic: http://www.qtcentre.org/threads/6684...-readAll-error
The author resolved it, but the solution was apparently so self-evident that no details were given.
My function is as follows:
if (ok) {
file.write(stuff);
file.close();
}
else
qDebug
() <<
QString("DownloadManager::saveToDisk(%1) - Failed: %2").
arg(fileName
).
arg(file.
errorString());
return ok;
}
bool DownloadManager::saveToDisk(const QString &fileName, QIODevice *data) {
QFile file(fileName);
bool ok = file.open(QIODevice::WriteOnly);
if (ok) {
QByteArray stuff = data->readAll(); // BOOM!
file.write(stuff);
file.close();
}
else
qDebug() << QString("DownloadManager::saveToDisk(%1) - Failed: %2").arg(fileName).arg(file.errorString());
return ok;
}
To copy to clipboard, switch view to plain text mode
And here is the calling code:
void DownloadManager::onFinished() {
const QUrl urlObj
= m_reply
->url
();
const QString url
= urlObj.
toString();
const QNetworkReply::NetworkError err = m_reply->error();
if (err) {
qDebug
() <<
QString("DownloadManager::onFinished(%1) - Error: %2").
arg(url
).
arg(m_reply
->errorString
());
emit failure(url, (err == QNetworkReply::OperationCanceledError ? CanceledByUser : Network));
}
else {
const QString fileName
= absoluteSaveFileName
(urlObj
);
if (saveToDisk(fileName, m_reply))
emit success(url, fileName);
else {
qDebug
() <<
QString("DownloadManager::onFinished(%1) - Failed to save to '%2'").
arg(url
).
arg(fileName
);
emit failure(url, FileIO);
}
}
m_reply->deleteLater();
if (m_queue.isEmpty())
setIsDownloading(false);
else {
m_reply = m_manager.get(m_queue.takeFirst());
Q_ASSERT_X(m_reply, "onFinished", "Null pointer to QNetworkReply!");
#ifndef QT_NO_SSL
connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(sslErrors(QList<QSslError>)));
#endif
}
}
void DownloadManager::onFinished() {
const QUrl urlObj = m_reply->url();
const QString url = urlObj.toString();
const QNetworkReply::NetworkError err = m_reply->error();
if (err) {
qDebug() << QString("DownloadManager::onFinished(%1) - Error: %2").arg(url).arg(m_reply->errorString());
emit failure(url, (err == QNetworkReply::OperationCanceledError ? CanceledByUser : Network));
}
else {
const QString fileName = absoluteSaveFileName(urlObj);
if (saveToDisk(fileName, m_reply))
emit success(url, fileName);
else {
qDebug() << QString("DownloadManager::onFinished(%1) - Failed to save to '%2'").arg(url).arg(fileName);
emit failure(url, FileIO);
}
}
m_reply->deleteLater();
if (m_queue.isEmpty())
setIsDownloading(false);
else {
m_reply = m_manager.get(m_queue.takeFirst());
Q_ASSERT_X(m_reply, "onFinished", "Null pointer to QNetworkReply!");
#ifndef QT_NO_SSL
connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(sslErrors(QList<QSslError>)));
#endif
}
}
To copy to clipboard, switch view to plain text mode
The cited topic and error message certainly make this look like a threading issue, but I need a hand with understanding and resolving it. I should add that I'm using Qt Creator 4.2.2 based on Qt 5.8.0.
Thanks in advance.
Bookmarks