QNetworkReply segfaults randomly when I invoke `QIODevice::readAll()`, usually something to do with corrupted Data. Is this because it is still open?

59 Views Asked by At

I am having a real hard time tracking down this bug. Here is the basic example; It requires a fast connectiona and many simultaneous downloads. When it hits, is fairly random.

#ifndef DOWNLOAD_H
#define DOWNLOAD_H

#include <QThread>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QEventLoop>
#include <QFile>

class Download : public QThread
{
    Q_OBJECT
public:
    Download( const QString &path, QUrl url, QObject* parent = nullptr )
    : QThread(parent)
    , f_Local(path)
    , m_Url(url)
    {
        this->start();
    };

private:
    QFile f_Local;
    const QUrl m_Url;

    void run() override
    {
        QNetworkRequest request( m_Url );
        QNetworkAccessManager nam;
        QNetworkReply *reply = nam.get(request);
        {
            reply->setParent(&nam);
        }

        QEventLoop waitForDownload;
        connect( reply, &QNetworkReply::readyRead, [this, &reply](){
            if ( !f_Local.open(  QIODevice::WriteOnly | QIODevice::Append  ) ) {
                return;
            }
            f_Local.write( reply->readAll() );
            f_Local.close();
            qDebug()
            << f_Local.fileName()
            << Qt::endl
            << f_Local.size() << "/"
            << reply->header( QNetworkRequest::ContentLengthHeader ).toLongLong()
            << Qt::endl
            << m_Url.toDisplayString()
            << Qt::endl;
        });
        connect( reply, &QNetworkReply::finished, &waitForDownload, &QEventLoop::quit );
        waitForDownload.exec();
    }
};

#endif // DOWNLOAD_H

This is a gdb trace and it shows that some corruption is occurring when QNetworkReply is trying to free its cache

The important thing to note, is that I am calling readAll() on readyRead() as opposed to finished(), meaning it is still capable of writing data to the QNetworkReply object. Would this perhaps be an issue if readAll() is clearing the buffer while it is simultaneously writing to it? I was working under the assumption that QIODevice / QNetworkReply protected against this. If it doesn't; is there a mutex I can invoke to protect against this?

The other important thing to note is that my class is threaded, and I am running nearly a dozen threads at the same time, and hence there are a dozen QNetworkAccessManager objects as well as a subsequent QNetworkReply etc.

I had thought that perhaps QNetworkAccessManager had been deleted before Reply was ready to finish, but preventing this still gives me the bug.

Is my suspicion correct, or is there something else at play here?

0

There are 0 best solutions below