QAbstractSocket: do not fail writing on read buffer overflow
canReadNotification() could return 'false' if either the socket has been closed, or the read buffer has reached the maximum size. Because of this duality, waitForBytesWritten() should not fail as a result of a canReadNotification() call. Change-Id: I9a15fa174a3b982a7ce404913caa38fc19f64622 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
This commit is contained in:
parent
d930c8b5fc
commit
bec47545dc
@ -2253,8 +2253,10 @@ bool QAbstractSocket::waitForBytesWritten(int msecs)
|
|||||||
forever {
|
forever {
|
||||||
bool readyToRead = false;
|
bool readyToRead = false;
|
||||||
bool readyToWrite = false;
|
bool readyToWrite = false;
|
||||||
if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite, true, !d->writeBuffer.isEmpty(),
|
if (!d->socketEngine->waitForReadOrWrite(&readyToRead, &readyToWrite,
|
||||||
qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
|
!d->readBufferMaxSize || d->buffer.size() < d->readBufferMaxSize,
|
||||||
|
!d->writeBuffer.isEmpty(),
|
||||||
|
qt_subtract_from_timeout(msecs, stopWatch.elapsed()))) {
|
||||||
#if defined (QABSTRACTSOCKET_DEBUG)
|
#if defined (QABSTRACTSOCKET_DEBUG)
|
||||||
qDebug("QAbstractSocket::waitForBytesWritten(%i) failed (%i, %s)",
|
qDebug("QAbstractSocket::waitForBytesWritten(%i) failed (%i, %s)",
|
||||||
msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
|
msecs, d->socketEngine->error(), d->socketEngine->errorString().toLatin1().constData());
|
||||||
@ -2269,8 +2271,7 @@ bool QAbstractSocket::waitForBytesWritten(int msecs)
|
|||||||
#if defined (QABSTRACTSOCKET_DEBUG)
|
#if defined (QABSTRACTSOCKET_DEBUG)
|
||||||
qDebug("QAbstractSocket::waitForBytesWritten calls canReadNotification");
|
qDebug("QAbstractSocket::waitForBytesWritten calls canReadNotification");
|
||||||
#endif
|
#endif
|
||||||
if(!d->canReadNotification())
|
d->canReadNotification();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,6 +197,7 @@ private slots:
|
|||||||
void clientSendDataOnDelayedDisconnect();
|
void clientSendDataOnDelayedDisconnect();
|
||||||
void serverDisconnectWithBuffered();
|
void serverDisconnectWithBuffered();
|
||||||
void socketDiscardDataInWriteMode();
|
void socketDiscardDataInWriteMode();
|
||||||
|
void writeOnReadBufferOverflow();
|
||||||
void readNotificationsAfterBind();
|
void readNotificationsAfterBind();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
@ -3067,6 +3068,40 @@ void tst_QTcpSocket::socketDiscardDataInWriteMode()
|
|||||||
delete socket;
|
delete socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test waitForBytesWritten() does not fail on read buffer overflow
|
||||||
|
void tst_QTcpSocket::writeOnReadBufferOverflow()
|
||||||
|
{
|
||||||
|
QFETCH_GLOBAL(bool, setProxy);
|
||||||
|
if (setProxy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QTcpServer tcpServer;
|
||||||
|
QTcpSocket *socket = newSocket();
|
||||||
|
|
||||||
|
QVERIFY(tcpServer.listen(QHostAddress::LocalHost));
|
||||||
|
socket->setReadBufferSize(1);
|
||||||
|
socket->connectToHost(tcpServer.serverAddress(), tcpServer.serverPort());
|
||||||
|
QVERIFY(socket->waitForConnected(5000));
|
||||||
|
QCOMPARE(socket->state(), QAbstractSocket::ConnectedState);
|
||||||
|
|
||||||
|
// Accept connection on server side
|
||||||
|
QVERIFY2(tcpServer.waitForNewConnection(5000), "Network timeout");
|
||||||
|
QTcpSocket *newConnection = tcpServer.nextPendingConnection();
|
||||||
|
QVERIFY(newConnection != nullptr);
|
||||||
|
QCOMPARE(newConnection->write("1", 2), Q_INT64_C(2));
|
||||||
|
QVERIFY(newConnection->flush());
|
||||||
|
|
||||||
|
// Wait for buffer overflow
|
||||||
|
QVERIFY(socket->waitForReadyRead(5000));
|
||||||
|
QCOMPARE(socket->bytesAvailable(), Q_INT64_C(1));
|
||||||
|
// Write data and wait for successful send
|
||||||
|
QVERIFY(socket->putChar(0));
|
||||||
|
QVERIFY(socket->waitForBytesWritten(5000));
|
||||||
|
|
||||||
|
delete newConnection;
|
||||||
|
delete socket;
|
||||||
|
}
|
||||||
|
|
||||||
// Test that the socket does not enable the read notifications in bind()
|
// Test that the socket does not enable the read notifications in bind()
|
||||||
void tst_QTcpSocket::readNotificationsAfterBind()
|
void tst_QTcpSocket::readNotificationsAfterBind()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user