diff options
| author | Mårten Nordheim <marten.nordheim@qt.io> | 2025-05-06 16:30:27 +0200 |
|---|---|---|
| committer | Mårten Nordheim <marten.nordheim@qt.io> | 2025-05-19 13:03:27 +0200 |
| commit | b0b9adf06675c5caa37105ceee157245e3dcca21 (patch) | |
| tree | e58e44f5306e5e6c0672c65b68edfd275bb5b040 /src/network/access/qhttp2protocolhandler.cpp | |
| parent | 7be5b476177bd86d79acc14f5a9254387db34e04 (diff) | |
Http2: remove any reference to HttpReply when deleted
Prior to switching the protocol handler to use QHttp2Connection this
particular issue (see bugreport) was not a problem because the handling
of the IO-device being destroyed was simply to drop any pointer to
it.
QHttp2Stream, however, also has to keep track of the lifetime of
the IO-device, because it needs to abort the stream if the data
it's uploading is destroyed earlier than expected.
Now, since QHttp2Stream might also have other errors come up, we
have to connect to the generic 'errorOccurred' signal from it and
handle whatever issues arise, notifying our users that the request
for some reason cannot be fulfilled.
It's thanks to this part that we were now, in certain cases,
grabbing a stale pointer to the HttpNetworkReply and trying to
call functions on it.
We fix this somewhat indirectly. Because, after a HttpReply is
destroyed, we shouldn't even have any references to it in the
first place. And while it would usually be done as part of
handling the deleted() signal, we actually disconnect from
HttpNetworkReply's signals when we have processed one of the
finished*() functions. But since we were still connected to the stream's
signals we would still try to handle it.
For the http1 protocol handler this was already handled in
QHttpNetworkConnection::removeReply, which the HttpNetworkReply itself
calls at start of destruction. The function will go through any place
that the reply can be referenced and removes it. For http/2 it would
remove it from the list of requests yet to be sent, but not from the
in-progress list. So, we now add a new virtual function to the
AbstractProtocolHandler and specialize it in Http2 to handle exactly
this.
Fixes: QTBUG-136549
Pick-to: 6.9.1 6.9
Change-Id: Ie41863677a3b163f77d10bc3904ca515f6840be3
Reviewed-by: Mate Barany <mate.barany@qt.io>
Diffstat (limited to 'src/network/access/qhttp2protocolhandler.cpp')
| -rw-r--r-- | src/network/access/qhttp2protocolhandler.cpp | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 87dc504ee12..a99921f5288 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -151,15 +151,6 @@ void QHttp2ProtocolHandler::handleConnectionClosure() h2Connection->handleConnectionClosure(); } -void QHttp2ProtocolHandler::_q_replyDestroyed(QObject *reply) -{ - QPointer<QHttp2Stream> stream = streamIDs.take(reply); - requestReplyPairs.remove(stream); - QObject::disconnect(stream, nullptr, this, nullptr); - if (stream && stream->isActive()) - stream->sendRST_STREAM(CANCEL); -} - void QHttp2ProtocolHandler::_q_uploadDataDestroyed(QObject *uploadData) { QPointer<QHttp2Stream> stream = streamIDs.take(uploadData); @@ -262,6 +253,25 @@ bool QHttp2ProtocolHandler::sendRequest() return true; } +/*! + \internal + This gets called during destruction of \a reply, so do not call any functions + on \a reply. We check if there is a stream associated with the reply and, + if there is, we remove the request-reply pair associated with this stream, + delete the stream and return \c{true}. Otherwise nothing happens and we + return \c{false}. +*/ +bool QHttp2ProtocolHandler::tryRemoveReply(QHttpNetworkReply *reply) +{ + QHttp2Stream *stream = streamIDs.take(reply); + if (stream) { + requestReplyPairs.remove(stream); + stream->deleteLater(); + return true; + } + return false; +} + bool QHttp2ProtocolHandler::sendHEADERS(QHttp2Stream *stream, QHttpNetworkRequest &request) { using namespace HPack; @@ -623,8 +633,6 @@ void QHttp2ProtocolHandler::connectStream(const HttpMessagePair &message, QHttp2 auto *replyPrivate = reply->d_func(); replyPrivate->connection = m_connection; replyPrivate->connectionChannel = m_channel; - connect(reply, &QObject::destroyed, this, &QHttp2ProtocolHandler::_q_replyDestroyed, - Qt::UniqueConnection); reply->setHttp2WasUsed(true); QPointer<QHttp2Stream> &oldStream = streamIDs[reply]; |
