Don't destory socket and request objects while handling a request

Task-number: QTBUG-84617
Change-Id: Ibf98fb329c817ae39f66e539cdb30a4194cb3b42
Reviewed-by: Mikhail Svetkin <mikhail.svetkin@gmail.com>
This commit is contained in:
Mikhail Svetkin 2020-06-04 23:53:12 +02:00
parent 7e29e0dfeb
commit 2a67efadf1
4 changed files with 35 additions and 2 deletions

View File

@ -63,8 +63,12 @@ void QAbstractHttpServerPrivate::handleNewConnections()
handleReadyRead(socket, request);
});
QObject::connect(socket, &QTcpSocket::disconnected, &QObject::deleteLater);
QObject::connect(socket, &QObject::destroyed, [request] () {
QObject::connect(socket, &QTcpSocket::disconnected, socket, [request, socket] () {
if (!request->d->handling)
socket->deleteLater();
});
QObject::connect(socket, &QObject::destroyed, socket, [request] () {
delete request;
});
}
@ -118,8 +122,12 @@ void QAbstractHttpServerPrivate::handleReadyRead(QTcpSocket *socket,
}
socket->commitTransaction();
request->d->handling = true;
if (!q->handleRequest(*request, socket))
Q_EMIT q->missingHandler(*request, socket);
request->d->handling = false;
if (socket->state() == QAbstractSocket::UnconnectedState)
socket->deleteLater();
}
QAbstractHttpServer::QAbstractHttpServer(QObject *parent)

View File

@ -88,6 +88,7 @@ public:
void clear();
QHostAddress remoteAddress;
bool handling{false};
private:
static http_parser_settings httpParserSettings;

View File

@ -37,6 +37,7 @@
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qmimedatabase.h>
#include <QtNetwork/qtcpsocket.h>
QT_BEGIN_NAMESPACE
@ -353,6 +354,9 @@ QVector<QByteArray> QHttpServerResponse::headers(const QByteArray &name) const
void QHttpServerResponse::write(QHttpServerResponder &&responder) const
{
Q_D(const QHttpServerResponse);
if (responder.socket()->state() != QAbstractSocket::ConnectedState)
return;
responder.writeStatusLine(d->statusCode);
for (auto &&header : d->headers)

View File

@ -46,6 +46,7 @@
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qjsonarray.h>
#include <QtCore/qtimer.h>
#include <QtNetwork/qnetworkaccessmanager.h>
#include <QtNetwork/qnetworkreply.h>
@ -130,6 +131,7 @@ private slots:
void invalidRouterArguments();
void checkRouteLambdaCapture();
void afterRequest();
void disconnectedInEventLoop();
private:
void checkReply(QNetworkReply *reply, const QString &response);
@ -915,6 +917,24 @@ void tst_QHttpServer::checkReply(QNetworkReply *reply, const QString &response)
reply->deleteLater();
};
void tst_QHttpServer::disconnectedInEventLoop()
{
httpserver.route("/event-loop/", [] () {
QEventLoop loop;
QTimer::singleShot(1000, &loop, &QEventLoop::quit);
loop.exec();
return QHttpServerResponse::StatusCode::Ok;
});
const QUrl requestUrl(urlBase.arg("/event-loop/"));
auto reply = networkAccessManager.get(QNetworkRequest(requestUrl));
QTimer::singleShot(500, reply, &QNetworkReply::abort); // cancel connection
QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
reply->deleteLater();
}
QT_END_NAMESPACE
Q_DECLARE_METATYPE(CustomArg);