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);
#endifqDebug("[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!