Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Correct code to prevent memory leak with QNAM HTTP Get request to nonexistent URL with Qt 5.14.2

Correct code to prevent memory leak with QNAM HTTP Get request to nonexistent URL with Qt 5.14.2

Scheduled Pinned Locked Moved Solved General and Desktop
qnamtimeoutqt5.14.2http getqnetworkaccessm
5 Posts 3 Posters 778 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • WilliamJW Offline
    WilliamJW Offline
    WilliamJ
    wrote on last edited by
    #1

    What is the correct way to handle HTTP Get requests to a nonexistent URL in the case of the remote server going down?
    I'm testing the edge case of the remote server going down.

    I am seeing what I think is a memory leak and I am unsure of what I am supposed to be doing to clean up the request in the event of a timeout occurring.
    I am using Syrupy to periodically capture the output of ps to see memory usage.

    Note - I am aware of Qt 5.15 including a new API call (setTransferTimeout) to set a timeout length but I cannot update on this project yet.

    Testing on Ubuntu 20.04 with Linux kernel 4.19 as well as a Raspberry Pi 4 (Buster) with Linux kernel 5.4.79

    Syrupy log output from an 1.5 hour run:

         PID         DATE      TIME      ELAPSED    CPU    MEM       RSS     VSIZE       CMD
        4814   2020-12-15  17:09:53        00:00    0.0    0.1      4756     36456  ./memoryprofiletest
        4814   2020-12-15  17:10:53        01:00    0.5    0.1      5024     55028  ./memoryprofiletest
        4814   2020-12-15  17:11:53        02:00    0.5    0.1      5620     55156  ./memoryprofiletest
        4814   2020-12-15  17:12:54        03:00    0.5    0.2      8316     55156  ./memoryprofiletest
        4814   2020-12-15  17:13:54        04:00    0.5    0.2      8316     55156  ./memoryprofiletest
        4814   2020-12-15  17:14:54        05:01    0.5    0.2      8316     55156  ./memoryprofiletest
    ...
        4814   2020-12-15  17:23:55        14:02    0.5    0.2      8512     55412  ./memoryprofiletest
        4814   2020-12-15  17:24:55        15:02    0.5    0.2      8512     55412  ./memoryprofiletest
        4814   2020-12-15  17:25:55        16:02    0.5    0.2      8512     55412  ./memoryprofiletest
        4814   2020-12-15  17:26:55        17:02    0.5    0.2      8512     55412  ./memoryprofiletest
    ...
        4814   2020-12-15  17:37:57        28:04    0.5    0.2      8932     55668  ./memoryprofiletest
        4814   2020-12-15  17:38:57        29:04    0.5    0.2      8932     55668  ./memoryprofiletest
        4814   2020-12-15  17:39:57        30:04    0.5    0.2      8984     55796  ./memoryprofiletest
        4814   2020-12-15  17:40:57        31:04    0.5    0.2      8984     55796  ./memoryprofiletest
        4814   2020-12-15  17:41:57        32:04    0.5    0.2      8984     55796  ./memoryprofiletest
    ...
        4814   2020-12-15  17:52:59        43:05    0.5    0.2      9132     56052  ./memoryprofiletest
        4814   2020-12-15  17:53:59        44:06    0.5    0.2      9132     56052  ./memoryprofiletest
        4814   2020-12-15  17:54:59        45:06    0.5    0.2      9132     56052  ./memoryprofiletest
        4814   2020-12-15  17:55:59        46:06    0.5    0.2      9192     56180  ./memoryprofiletest
        4814   2020-12-15  17:56:59        47:06    0.5    0.2      9192     56180  ./memoryprofiletest
    ...
        4814   2020-12-15  18:08:01        58:07    0.5    0.2      9516     56436  ./memoryprofiletest
        4814   2020-12-15  18:09:01        59:07    0.5    0.2      9516     56436  ./memoryprofiletest
        4814   2020-12-15  18:10:01     01:00:08    0.5    0.2      9516     56436  ./memoryprofiletest
        4814   2020-12-15  18:11:01     01:01:08    0.5    0.2      9516     56436  ./memoryprofiletest
    ...
        4814   2020-12-15  18:23:03     01:13:09    0.5    0.2      9728     56692  ./memoryprofiletest
        4814   2020-12-15  18:24:03     01:14:09    0.5    0.2     10056     56820  ./memoryprofiletest
        4814   2020-12-15  18:25:03     01:15:10    0.5    0.2     10056     56820  ./memoryprofiletest
        4814   2020-12-15  18:26:03     01:16:10    0.5    0.2     10056     56820  ./memoryprofiletest
    ...
        4814   2020-12-15  18:38:05     01:28:11    0.5    0.2     10196     57076  ./memoryprofiletest
        4814   2020-12-15  18:39:05     01:29:11    0.5    0.2     10196     57076  ./memoryprofiletest
        4814   2020-12-15  18:40:05     01:30:12    0.5    0.2     10196     57076  ./memoryprofiletest
    

    I've created the simplest possible test case below which is showing the memory increasing above:

    //
    // main.cpp
    //
    
    #include <QCoreApplication>
    #include "memoryprofiletest.h"
    
    int main(int argc, char* argv[]) {
        QCoreApplication a(argc, argv);
        MemoryProfileTest memoryProfileTest;
    
        return a.exec();
    }
    
    // =============================================================
    
    //
    // memoryprofiletest.h
    //
    
    #ifndef MEMORYPROFILETEST_H
    #define MEMORYPROFILETEST_H
    
    #include <QObject>
    #include <QtCore>
    #include <QtNetwork>
    
    class MemoryProfileTest : public QObject
    {
        Q_OBJECT
    public:
        explicit MemoryProfileTest(QObject* parent = nullptr);
    
    private:
        void executeNetworkRequest();
    
        QTimer instanceTimer;
        QNetworkAccessManager networkAccessManager;
    
    private slots:
    
        void executeRequest();
    };
    
    #endif // MEMORYPROFILETEST_H
    
    // =============================================================
    
    //
    // memoryprofiletest.cpp
    //
    
    #include "memoryprofiletest.h"
    
    MemoryProfileTest::MemoryProfileTest(QObject *parent)
        : QObject(parent),
        networkAccessManager(this)
    {
        qDebug() << "Compiled with Qt Version " << QT_VERSION_STR;
        qDebug() << "Running with Qt Version " << qVersion();
    
        instanceTimer.callOnTimeout(this, &MemoryProfileTest::executeRequest);
        instanceTimer.start(500); // 500 milliseconds
    }
    
    void MemoryProfileTest::executeNetworkRequest()
    {
        auto endpoint = QUrl("http://localhost/api/1.0/aService/aNonexistentEndpoint");
    
        QNetworkRequest request(endpoint);
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    
        auto reply = networkAccessManager.get(request);
    
        connect(reply, &QNetworkReply::finished, reply, [reply]() {
            if (reply->error() != QNetworkReply::NoError) {
                qDebug() << "finished - error:" << reply->errorString();
            } else {
                auto replyData = reply->readAll();
                // Do something useful with the data
            }
    
            reply->deleteLater();
            qDebug() << "finished - deleteLater called";
        });
    };
    
    void MemoryProfileTest::executeRequest()
    {
        executeNetworkRequest();
    }
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by SGaist
      #2

      Hi and welcome to devnet,

      You should also handle the errorOccured signal.

      I might be wrong but since the URL does not exists then the processing will not have been started and thus finished has no reason to be emitted.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • WilliamJW Offline
        WilliamJW Offline
        WilliamJ
        wrote on last edited by
        #3

        Thank you for the welcome and the reply!
        The errorOccured signal is not available until Qt 5.15 so I have added the error signal that's available in Qt 5.14.

        I am running another test now to capture memory usage from a long running test.

        Here's the current program output:

        Compiled with Qt Version  5.14.2
        Running with Qt Version  5.14.2
        error lambda: "Connection refused"
        error lambda - deleteLater called
        finished lambda - error: "Connection refused"
        finished lambda - deleteLater called
        error lambda: "Connection refused"
        error lambda - deleteLater called
        finished lambda - error: "Connection refused"
        finished lambda - deleteLater called
        ... 
        continues...
        

        Updated test code below:

        //
        // main.cpp
        //
        
        #include <QCoreApplication>
        #include "memoryprofiletest.h"
        
        int main(int argc, char* argv[]) {
            QCoreApplication a(argc, argv);
            MemoryProfileTest memoryProfileTest;
        
            return a.exec();
        }
        
        // =============================================================
        
        //
        // memoryprofiletest.h
        //
        
        #ifndef MEMORYPROFILETEST_H
        #define MEMORYPROFILETEST_H
        
        #include <QObject>
        #include <QtCore>
        #include <QtNetwork>
        
        class MemoryProfileTest : public QObject
        {
            Q_OBJECT
        public:
            explicit MemoryProfileTest(QObject* parent = nullptr);
        
        private:
            void executeNetworkRequest();
        
            QTimer instanceTimer;
            QNetworkAccessManager networkAccessManager;
        
        private slots:
        
            void executeRequest();
        };
        
        #endif // MEMORYPROFILETEST_H
        
        // =============================================================
        
        //
        // memoryprofiletest.cpp
        //
        
        #include "memoryprofiletest.h"
        
        MemoryProfileTest::MemoryProfileTest(QObject *parent)
            : QObject(parent),
            networkAccessManager(this)
        {
            qDebug() << "Compiled with Qt Version " << QT_VERSION_STR;
            qDebug() << "Running with Qt Version " << qVersion();
        
            instanceTimer.callOnTimeout(this, &MemoryProfileTest::executeRequest);
            instanceTimer.start(500); // 500 milliseconds
        }
        
        void MemoryProfileTest::executeNetworkRequest()
        {
            auto endpoint = QUrl("http://localhost/api/1.0/aService/aNonexistentEndpoint");
        
            QNetworkRequest request(endpoint);
            request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
        
            auto reply = networkAccessManager.get(request);
        
            connect(reply, &QNetworkReply::finished, reply, [reply]() {
                if (reply->error() != QNetworkReply::NoError) {
                    qDebug() << "finished lambda - error:" << reply->errorString();
                } else {
                    auto replyData = reply->readAll();
                    // Do something useful with the data
                }
        
                reply->deleteLater();
                qDebug() << "finished lambda - deleteLater called";
            });
        
            connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), [reply] (QNetworkReply::NetworkError code){
        
                if (reply->error() != QNetworkReply::NoError) {
                    qDebug() << "error lambda:" << reply->errorString();
                }
        
                reply->deleteLater();
                qDebug() << "error lambda - deleteLater called";
            });
        };
        
        void MemoryProfileTest::executeRequest()
        {
            executeNetworkRequest();
        }
        
        1 Reply Last reply
        0
        • Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by Christian Ehrlicher
          #4

          See https://bugreports.qt.io/browse/QTBUG-88063 and https://bugreports.qt.io/browse/QTBUG-88248

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          1
          • WilliamJW Offline
            WilliamJW Offline
            WilliamJ
            wrote on last edited by WilliamJ
            #5

            Thank you Christian!

            https://bugreports.qt.io/browse/QTBUG-88063 describes exactly what I've been seeing.

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved