Results 1 to 9 of 9

Thread: Memory leak in my threaded SSL server application

  1. #1
    Join Date
    Mar 2010
    Posts
    16
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Memory leak in my threaded SSL server application

    Hi All,

    I built an SSL server by subclassing the QTcpServer. The stress test I did is connecting and disconnecting from the server about 200,000 times (client connects and disconnects each 100ms). I can see that the memory consumption gets larger as the number of connections and drops increase.

    My client application on the other hand doesn't have this phenomena.

    I tested the server and client under Windows XP and Ubuntu 9.04.

    Honestly I don't know if this is a QT issue or a bug in my application. But I will be happy if someone could guide me where the memory leak could be.

    Please feel free to comment on my code as well.

    Thank you in advance!

    And here is the code:
    Pay attention that the defines NO_AUTH_TIME_LIMIT and UNSECURE_CONNECTION are off!

    sslserver.h:
    Qt Code:
    1. #ifndef SSLSERVER_H
    2. #define SSLSERVER_H
    3.  
    4. #include <QTcpServer>
    5. #include <QSslSocket>
    6.  
    7. class SslServer : public QTcpServer
    8. {
    9. Q_OBJECT
    10. public:
    11. SslServer(QObject *parent=0);
    12. ~SslServer();
    13.  
    14. protected:
    15. void incomingConnection(int socketDescriptor);
    16.  
    17. private slots:
    18. void error(QAbstractSocket::SocketError err);
    19. };
    20. #endif // SSLSERVER_H
    To copy to clipboard, switch view to plain text mode 


    sslserver.c:
    Qt Code:
    1. #include "sslserver.h"
    2. #include "messagethread.h"
    3.  
    4. SslServer::SslServer(QObject *parent):QTcpServer(parent)
    5. {
    6. }
    7.  
    8. SslServer::~SslServer()
    9. {
    10. }
    11.  
    12. void SslServer::incomingConnection(int socketDescriptor)
    13. {
    14. MessageThread *thread = new MessageThread(socketDescriptor, this);
    15. connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    16. thread->start();
    17. }
    18. void SslServer::error(QAbstractSocket::SocketError err)
    19. {
    20. qDebug()<<tr("Error: %1").arg(err);
    21. }
    To copy to clipboard, switch view to plain text mode 


    messagethread.h:
    Qt Code:
    1. #ifndef MESSAGETHREAD_H
    2. #define MESSAGETHREAD_H
    3.  
    4. #include <QThread>
    5. #include <QSslSocket>
    6. #include <QAbstractSocket>
    7. #include <QTimer>
    8. #include <QMutex>
    9.  
    10. #define THREAD_MAX_PENDING_CONN_INTERVAL (2000)
    11.  
    12. class MessageThread : public QThread
    13. {
    14. Q_OBJECT
    15. public:
    16. MessageThread(int socketDescriptor, QObject *parent = 0);
    17. ~MessageThread();
    18.  
    19. protected:
    20. void run(void);
    21.  
    22. private:
    23. int m_socketDescriptor; // Socket descriptor of the connection
    24. quint16 m_numOfExpectedBytes; // Number of expected bytes from the client
    25. quint32 m_currentUserId; // Current user ID
    26. bool m_cleanExitDone; // Indicates that an exit procedure was done
    27. QMutex *m_mutex; // Mutex to perform clean exit without interrupts
    28.  
    29. #ifdef UNSECURE_CONNECTION // Define m_socket to be SSL or TCP socket
    30. QTcpSocket *m_socket;
    31. #else
    32. QSslSocket *m_socket;
    33. #endif
    34.  
    35. #ifndef NO_AUTH_TIME_LIMIT // If NO_AUTH_TIME_LIMIT is NOT present, the server will reject an unauthorized
    36. QTimer *m_authTimer; // connection which is held for a defined time frame
    37. bool m_authorized;
    38. #endif
    39.  
    40. private slots:
    41. void processReadyRead(void);
    42. void checkPending(void);
    43. void performCleanExit(void);
    44. };
    45.  
    46. #endif // MESSAGETHREAD_H
    To copy to clipboard, switch view to plain text mode 


    messagethread.c:
    Qt Code:
    1. #include "messagethread.h"
    2. #include <QIODevice>
    3. #include <QDataStream>
    4. #include <QAbstractSocket>
    5. #include <QFile>
    6. #include <QCoreApplication>
    7. #include <QDebug>
    8.  
    9. MessageThread::MessageThread(int socketDescriptor, QObject *parent):QThread(parent)
    10. {
    11. m_socketDescriptor = socketDescriptor;
    12. m_numOfExpectedBytes = 0;
    13. m_cleanExitDone = false;
    14. m_mutex = new QMutex();
    15. }
    16.  
    17. MessageThread::~MessageThread()
    18. {
    19. delete m_mutex;
    20. }
    21.  
    22. void MessageThread::run(void)
    23. {
    24. #ifdef UNSECURE_CONNECTION
    25. m_socket = new QTcpSocket();
    26. #else
    27. m_socket = new QSslSocket();
    28. #endif
    29. if (m_socket->setSocketDescriptor(m_socketDescriptor))
    30. {
    31. QList<QSslCertificate> certificateList;
    32. certificateList.append(QSslCertificate());
    33. connect(m_socket, SIGNAL(readyRead()), this, SLOT(processReadyRead()), Qt::DirectConnection);
    34. connect(m_socket, SIGNAL(disconnected()), this, SLOT(performCleanExit()));
    35. #ifdef UNSECURE_CONNECTION
    36. // Nothing to do if the connection is unsecure
    37. #else
    38. // Add the key that will make the handshake
    39. m_socket->setPrivateKey(":/certs/my-key.pem");
    40. m_socket->setLocalCertificate(":/certs/my-cert.pem");
    41.  
    42. // Add the certificate authority to the list of certificate sent
    43. QFile f(":/certs/cacert.pem");
    44. f.open(QIODevice::ReadOnly);
    45. QSslCertificate cert(f.readAll());
    46. if (!cert.isValid())
    47. qDebug("Invaild certificate");
    48. m_socket->addCaCertificate(cert);
    49. m_socket->startServerEncryption();
    50. #endif
    51. }
    52. else
    53. {
    54. qDebug()<<tr("Could not create socket from descriptor");
    55. qDebug()<<m_socket->errorString();
    56. performCleanExit();
    57. }
    58. #ifndef NO_AUTH_TIME_LIMIT
    59. m_authorized = false;
    60. m_authTimer = new QTimer();
    61. connect(m_authTimer, SIGNAL(timeout()), this, SLOT(checkPending()), Qt::DirectConnection);
    62. m_authTimer->setInterval(THREAD_MAX_PENDING_CONN_INTERVAL);
    63. m_authTimer->setSingleShot(true);
    64. m_authTimer->start();
    65. #endif
    66. /* Call the event loop of the thread */
    67. exec();
    68. }
    69.  
    70. void MessageThread::performCleanExit(void)
    71. {
    72. m_mutex->lock();
    73. if (!m_cleanExitDone)
    74. {
    75. QAbstractSocket::SocketState s;
    76. m_cleanExitDone = true;
    77. s = m_socket->state();
    78. // Remove the connection
    79. if (s != QAbstractSocket::UnconnectedState && s != QAbstractSocket::ClosingState)
    80. {
    81. m_socket->disconnectFromHost();
    82. m_socket->waitForDisconnected();
    83. }
    84. disconnect(m_socket, 0, 0, 0);
    85. m_socket->deleteLater();
    86. }
    87. #ifndef NO_AUTH_TIME_LIMIT
    88. m_authTimer->deleteLater();
    89. #endif
    90. m_mutex->unlock();
    91. // Cover the case where we started with this function and the check pending
    92. // is called right after quit().
    93. QCoreApplication::processEvents();
    94. quit();
    95. }
    96.  
    97.  
    98. void MessageThread::processReadyRead(void)
    99. {
    100. if (m_socket->bytesAvailable() == 0)
    101. {
    102. return;
    103. }
    104. m_socket->readAll();
    105. //performCleanExit();
    106. }
    107.  
    108. void MessageThread::checkPending(void)
    109. {
    110. #ifndef NO_AUTH_TIME_LIMIT
    111. if (!m_authorized)
    112. {
    113. qDebug("Time out baby");
    114. performCleanExit();
    115. }
    116. #endif
    117. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Mar 2007
    Posts
    57
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Memory leak in my threaded SSL server application

    Did you check whether your MessageThread objects are really deleted when finished?

  3. #3
    Join Date
    Mar 2010
    Posts
    16
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Memory leak in my threaded SSL server application

    Yes, I printed a qDebug message on the MessageThread destructor when it is deleted and saw that the destructor is being called.

  4. #4
    Join Date
    Mar 2007
    Posts
    57
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Memory leak in my threaded SSL server application

    And the QTcpSocket/QSslSocket you create in MessageThread, are those deleted? Also, have you tried running with valgrind?

  5. #5
    Join Date
    Mar 2010
    Posts
    16
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Memory leak in my threaded SSL server application

    I am getting into the valgrind tool right now.

    About the QSslSocket, yes I am deleting it.
    One thing that decreased the memory leak noticeably (but not at all) is moving the following code from the "performCleanExit" function in the thread:
    Qt Code:
    1. m_socket->deleteLater();
    2. m_authTimer->deleteLater();
    To copy to clipboard, switch view to plain text mode 

    to the following code in thread destructor:
    Qt Code:
    1. delete m_socket;
    2. delete m_authTimer;
    To copy to clipboard, switch view to plain text mode 

    It may be related to that that the deleteLater() function does not enter the event loop (in order to be executed) before the thread is deleted.

    I will make further investigation and try to provide the client code as well in order to be able to reproduce the memory leak easily.

    Thanks in advance

  6. #6
    Join Date
    Feb 2008
    Posts
    50
    Thanks
    1
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Memory leak in my threaded SSL server application

    Hello, i`ll watch that thread closely for your final investigation about the memory leak. I`ve got the same problem with a multithreaded QSslSocket app myself and the memory of my server app goes up like ~700kb per client connect/disconnect. And my code is similar to yours.

  7. #7
    Join Date
    Mar 2010
    Posts
    16
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Memory leak in my threaded SSL server application

    By the way, I am using QT version 4.6.2.

    There is a reported bug about QSslSocket memory leak in the following link: http://bugreports.qt.nokia.com/browse/QTBUG-6504
    I do not know whether or not this the problem I am having here.

    Regards

  8. #8
    Join Date
    Mar 2010
    Posts
    16
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Memory leak in my threaded SSL server application

    Finally I found the code causing the memory leak:
    In the server side, setting the private key causes a memory leak. It seems like a bug in QT.

    The code that causes the memory leak is:
    Qt Code:
    1. m_socket->setPrivateKey(":/certs/my-key.pem"); // Add the key that will make the handshake
    2. m_socket->setLocalCertificate(":/certs/my-cert.pem");
    To copy to clipboard, switch view to plain text mode 

  9. #9
    Join Date
    Mar 2010
    Posts
    16
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Memory leak in my threaded SSL server application

    I think this is the bug reported:
    http://bugreports.qt.nokia.com/browse/QTBUG-6504

Similar Threads

  1. Multi Threaded Client Server application
    By live_07 in forum Qt Programming
    Replies: 0
    Last Post: 27th August 2009, 16:32
  2. Threaded TCP server
    By Sysace in forum Newbie
    Replies: 4
    Last Post: 21st February 2008, 12:37
  3. Threaded server.
    By nithinin2001 in forum Qt Programming
    Replies: 2
    Last Post: 15th November 2007, 16:37
  4. I have memory leak on every Qt3/4 application, Qt bug?
    By saugumas in forum Qt Programming
    Replies: 3
    Last Post: 14th November 2007, 19:33
  5. Memory Leak in my Application :-(
    By Svaths in forum Qt Programming
    Replies: 4
    Last Post: 27th July 2007, 19:42

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.