I am using qt4.5.3 / Linux.

It seems that QNetworkReply is not safe to be used in threads. When you compile the following code then it crashes at various different locations after a random time somewhere inside the Qt libraries.

When I chance the code by using QObject instead of QThread as superclass (and change some calls too), this code runs fine for hours. But here with threads it crashed very soon.

As I have investigated, there is a file qnetworkreplyimpl.cpp with the function QNetworkReplyImplPrivate::feed(const QByteArray &data) and there you find at line 377/378 the following code:
Qt Code:
  1. char *ptr = readBuffer.reserve(data.size());
  2. memcpy(ptr, data.constData(), data.size());
To copy to clipboard, switch view to plain text mode 
As I have investigated, data.size() returns different sizes when called in sequence inside a thread. This seems to be caused by the low level network reads which fill the buffer and which run in some other thread, e.g the main event loop. So, the QRingBuffer readBuffer reserves some space which is given with the first call, then some other thread expands the amount of available data in QByteArray data and when memcpy gets called, it filles more data than there is prepared space. ... and there is another call to data.size() in this function.

However, when I fix this, there are still crashes, since I am not very familiar with the code I cannot provide a real fix.


This is all my test source, the filename is xx.cpp. The only thing you need to do is to set up a http server with a reasonable large file. Voila, it crashes ... somewhere.
Qt Code:
  1. #include <Qt/qnetworkaccessmanager.h>
  2. #include <Qt/qnetworkreply.h>
  3. #include <Qt/qeventloop.h>
  4. #include <Qt/qapplication.h>
  5. #include <Qt/qthread.h>
  6.  
  7. class Hurz : public QThread
  8. {
  9. Q_OBJECT
  10.  
  11. public slots:
  12. void dataAvailable();
  13.  
  14. public:
  15. Hurz();
  16. void run();
  17.  
  18. private:
  19. QNetworkAccessManager *_manager;
  20. QNetworkReply *_reply;
  21. QNetworkRequest *_request;
  22. };
  23.  
  24. Hurz::Hurz()
  25. {
  26. }
  27.  
  28. void Hurz::run()
  29. {
  30. _manager = new QNetworkAccessManager();
  31.  
  32. // you need to change the url to a different one which sends you "endless" data, eg. a file with almost gigabytes of data
  33. _request = new QNetworkRequest(QUrl("http://big.server/with/extreme/large/file"));
  34. _reply = _manager->get(*_request);
  35. connect(_reply, SIGNAL(readyRead()), this, SLOT(dataAvailable()));
  36. exec();
  37. }
  38.  
  39. void Hurz::dataAvailable()
  40. {
  41. _reply->readAll();
  42. }
  43.  
  44. int main(int argc, char **argv)
  45. {
  46. QApplication app(argc, argv);
  47.  
  48. Hurz h;
  49. h.start();
  50.  
  51. QEventLoop evLoop;
  52. for(;;)
  53. evLoop.processEvents(QEventLoop::ExcludeUserInputEvents);
  54. }
  55.  
  56. #include "xx.moc"
To copy to clipboard, switch view to plain text mode