Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QTcpSocket readyRead signal waiting for nothing when writing a file in a separate thread



  • Hi,

    I have an annoying bug with my program. The main program is an HTTP web server. Another thread write sometime big amount of data into a file. My problem is when the thread is writing into the file, if i try to send a request to the web server, i got the newConnection signal but the related socket readyRead signal is sometimes coming very later. This problem is randomly happening, some request are very fast and sometimes it may take 5-10 seconds to get the readyRead signal. I use this server locally, so it cannot be a network speed problem. When the thread a finished to write into the file, everything become normal.

    Originally, I'm using libqxt-web to do this, but i'm able to reproduce the problem only with a QTcpServer into a simple program. Note that before using libqtx i was using a QTcpServer in a threaded context (using function incomingConnection, waitForReadyRead, waitForByteWritten...) which was not using the default event based system (newConnection, readyread...). This was working nice, but now i need to get it work with libqtx-web system. But, since i can reproduce the problem without libqxt, i think it's not a problem with that library.

    If i use a large enough sleep between each write into a file, this seems to solve the problem, but it's not a nice solution.

    So my simple program has the following code:

    main.cpp
    @
    int main(int argc, char *argv[])
    {
    qInstallMsgHandler(log_function);

    // Initialize the QT application
    QCoreApplication a(argc, argv);

    signal(SIGTERM, sig_term);
    signal(SIGINT, sig_term);

    // Port
    quint16 port = 8081;

    qDebug("[Main] Initialization server");
    WebServer *pWebServer = new WebServer(QHostAddress::Any, port);
    a.installEventFilter (pWebServer);

    qDebug("[Main] Starting server");
    pWebServer->start();

    qDebug("[Main] Starting worker");
    WorkerThread* pThread = new WorkerThread();
    pThread->start();

    qDebug("[Main] Starting the main loop");
    a.exec();
    qDebug("[Main] Exit the main loop");

    pThread->abort();
    qDebug("[WorkerThread] Wait worker thread");
    pThread->wait();
    qDebug("[WorkerThread] Destroy worker thread");
    delete pThread;

    qDebug("[WorkerThread] Destroy service");
    delete pWebServer;

    return 0;
    }@

    webserver.cpp
    @

    WebServer::WebServer(const QHostAddress &host, quint16 port)
    {
    m_host = host;
    m_port = port;
    m_count = 0;

    m_pServer = new QTcpServer();
    connect(m_pServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
    

    }

    WebServer::~WebServer()
    {

    }

    void WebServer::start()
    {
    m_pServer->listen(m_host, m_port);
    }

    void WebServer::acceptConnection()
    {
    qDebug("[WebServer] ---------------------->");
    qDebug("[WebServer] newConnection received");

    QTcpSocket* pSocket = m_pServer->nextPendingConnection ();
    QObject::connect(pSocket, SIGNAL(readyRead()), this, SLOT(incomingData()));
    QObject::connect(pSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
    QObject::connect(pSocket, SIGNAL(destroyed()), this, SLOT(destroyed()));
    }

    void WebServer::incomingData()
    {
    qDebug("[WebServer] readyRead received");

    QIODevice* pDevice = qobject_cast<QIODevice*>(sender());
    if (!pDevice) return;

    QString szResponse;
    m_count++;
    QString szContent = "Count is: " + QString::number(m_count);

    szResponse = "HTTP/1.1 200 OK\r\n"
    "Content-Type: text/html; charset=utf-8\r\n"
    "Content-Length: " + QString::number(szContent.length()) + "\r\n"
    "Connection: close\r\n"
    "\r\n" + szContent;

    qDebug("[WebServer] socket content sent: %s", qPrintable(szContent));

    pDevice->write(szResponse.toAscii());
    pDevice->close();
    }

    void WebServer::disconnected()
    {
    qDebug("[WebServer] socket disconnected");
    QIODevice* pDevice = qobject_cast<QIODevice*>(sender());
    if (!pDevice) return;

    pDevice->deleteLater();
    }

    void WebServer::destroyed()
    {
    qDebug("[WebServer] socket destroyed");
    qDebug("[WebServer] <----------------------");
    }
    @

    WorkerThread.cpp
    @

    void WorkerThread::run()
    {
    qDebug("[WorkerThread] Start worker thread");

    char* pBuffer;
    int sizeBuf;

    sizeBuf = 1000000;

    int iCount=4000;

    #ifdef MODE_C
    qDebug("[WorkerThread] Mode C");
    FILE * pFile;
    pFile = fopen ("fileout.dat" , "wb");
    if(pFile){
    while(iCount>0 && !m_bStop){
    //qDebug("[WorkerThread] Remaining: %d", iCount);

    pBuffer = (char*)malloc(sizeBuf * sizeof(char));

    fwrite (pBuffer, 1, sizeBuf, pFile);
    fflush (pFile);

    free(pBuffer);
    pBuffer = NULL;

    iCount--;

    //usleep(100);
    }
    }
    qDebug("[WorkerThread] Closing the file");
    fclose (pFile);
    #endif

    qDebug("[WorkerThread] End worker thread");
    }
    @

    Here the output log:

    @
    [lun. déc. 10 14:03:06 2012] [WebServer] ---------------------->
    ->[lun. déc. 10 14:03:06 2012] [WebServer] newConnection received
    ->[lun. déc. 10 14:03:10 2012] [WebServer] Event received SockAct(50)
    [lun. déc. 10 14:03:10 2012] [WebServer] Socket descriptor 262194
    [lun. déc. 10 14:03:10 2012] [WebServer] readyRead received
    [lun. déc. 10 14:03:10 2012] [WebServer] socket content sent: Count is: 3
    [lun. déc. 10 14:03:10 2012] [WebServer] Event received ChildAdded(68)
    [lun. déc. 10 14:03:10 2012] [WebServer] Event received SockAct(50)
    [lun. déc. 10 14:03:10 2012] [WebServer] Socket descriptor 262194
    [lun. déc. 10 14:03:10 2012] [WebServer] Event received ChildRemoved(71)
    [lun. déc. 10 14:03:10 2012] [WebServer] Event received ChildRemoved(71)
    [lun. déc. 10 14:03:10 2012] [WebServer] Event received ChildRemoved(71)
    [lun. déc. 10 14:03:10 2012] [WebServer] socket disconnected
    [lun. déc. 10 14:03:10 2012] [WebServer] Event received DeferredDelete(52)
    [lun. déc. 10 14:03:10 2012] [WebServer] socket destroyed
    [lun. déc. 10 14:03:10 2012] [WebServer] <----------------------
    @

    I'm working on Linux 3.2.0-3-amd64 on Mint LMDE. Someone can tell me, if i'm doing something wrong or if it's a bug in the Qt library?
    I don't see why Qt is blocking the readyRead signal because the main thread has nothing else to do.

    Thank you for you help!


Log in to reply