mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 819044 - better spdy stream cleanup when handling goaway r=honzab
--HG-- extra : rebase_source : 36de16ee094b4902e942546db3d681d2cdf2a4c0
This commit is contained in:
parent
87898044c6
commit
42617f77ea
@ -92,9 +92,12 @@ SpdySession2::ShutdownEnumerator(nsAHttpTransaction *key,
|
|||||||
|
|
||||||
// On a clean server hangup the server sets the GoAwayID to be the ID of
|
// On a clean server hangup the server sets the GoAwayID to be the ID of
|
||||||
// the last transaction it processed. If the ID of stream in the
|
// the last transaction it processed. If the ID of stream in the
|
||||||
// local session is greater than that it can safely be restarted because the
|
// local stream is greater than that it can safely be restarted because the
|
||||||
// server guarantees it was not partially processed.
|
// server guarantees it was not partially processed. Streams that have not
|
||||||
if (self->mCleanShutdown && (stream->StreamID() > self->mGoAwayID))
|
// registered an ID haven't actually been sent yet so they can always be
|
||||||
|
// restarted.
|
||||||
|
if (self->mCleanShutdown &&
|
||||||
|
(stream->StreamID() > self->mGoAwayID || !stream->HasRegisteredID()))
|
||||||
self->CloseStream(stream, NS_ERROR_NET_RESET); // can be restarted
|
self->CloseStream(stream, NS_ERROR_NET_RESET); // can be restarted
|
||||||
else
|
else
|
||||||
self->CloseStream(stream, NS_ERROR_ABORT);
|
self->CloseStream(stream, NS_ERROR_ABORT);
|
||||||
@ -102,6 +105,22 @@ SpdySession2::ShutdownEnumerator(nsAHttpTransaction *key,
|
|||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PLDHashOperator
|
||||||
|
SpdySession2::GoAwayEnumerator(nsAHttpTransaction *key,
|
||||||
|
nsAutoPtr<SpdyStream2> &stream,
|
||||||
|
void *closure)
|
||||||
|
{
|
||||||
|
SpdySession2 *self = static_cast<SpdySession2 *>(closure);
|
||||||
|
|
||||||
|
// these streams were not processed by the server and can be restarted.
|
||||||
|
// Do that after the enumerator completes to avoid the risk of
|
||||||
|
// a restart event re-entrantly modifying this hash.
|
||||||
|
if (stream->StreamID() > self->mGoAwayID || !stream->HasRegisteredID())
|
||||||
|
self->mGoAwayStreamsToRestart.Push(stream);
|
||||||
|
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
SpdySession2::~SpdySession2()
|
SpdySession2::~SpdySession2()
|
||||||
{
|
{
|
||||||
LOG3(("SpdySession2::~SpdySession2 %p mDownstreamState=%X",
|
LOG3(("SpdySession2::~SpdySession2 %p mDownstreamState=%X",
|
||||||
@ -1325,9 +1344,38 @@ SpdySession2::HandleGoAway(SpdySession2 *self)
|
|||||||
self->mGoAwayID =
|
self->mGoAwayID =
|
||||||
PR_ntohl(reinterpret_cast<uint32_t *>(self->mInputFrameBuffer.get())[2]);
|
PR_ntohl(reinterpret_cast<uint32_t *>(self->mInputFrameBuffer.get())[2]);
|
||||||
self->mCleanShutdown = true;
|
self->mCleanShutdown = true;
|
||||||
|
|
||||||
LOG3(("SpdySession2::HandleGoAway %p GOAWAY Last-Good-ID 0x%X.",
|
// Find streams greater than the last-good ID and mark them for deletion
|
||||||
self, self->mGoAwayID));
|
// in the mGoAwayStreamsToRestart queue with the GoAwayEnumerator. They can
|
||||||
|
// be restarted.
|
||||||
|
self->mStreamTransactionHash.Enumerate(GoAwayEnumerator, self);
|
||||||
|
|
||||||
|
// Process the streams marked for deletion and restart.
|
||||||
|
uint32_t size = self->mGoAwayStreamsToRestart.GetSize();
|
||||||
|
for (uint32_t count = 0; count < size; ++count) {
|
||||||
|
SpdyStream2 *stream =
|
||||||
|
static_cast<SpdyStream2 *>(self->mGoAwayStreamsToRestart.PopFront());
|
||||||
|
|
||||||
|
self->CloseStream(stream, NS_ERROR_NET_RESET);
|
||||||
|
if (stream->HasRegisteredID())
|
||||||
|
self->mStreamIDHash.Remove(stream->StreamID());
|
||||||
|
self->mStreamTransactionHash.Remove(stream->Transaction());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queued streams can also be deleted from this session and restarted
|
||||||
|
// in another one. (they were never sent on the network so they implicitly
|
||||||
|
// are not covered by the last-good id.
|
||||||
|
size = self->mQueuedStreams.GetSize();
|
||||||
|
for (uint32_t count = 0; count < size; ++count) {
|
||||||
|
SpdyStream2 *stream =
|
||||||
|
static_cast<SpdyStream2 *>(self->mQueuedStreams.PopFront());
|
||||||
|
self->CloseStream(stream, NS_ERROR_NET_RESET);
|
||||||
|
self->mStreamTransactionHash.Remove(stream->Transaction());
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG3(("SpdySession2::HandleGoAway %p GOAWAY Last-Good-ID 0x%X."
|
||||||
|
"live streams=%d\n", self, self->mGoAwayID,
|
||||||
|
self->mStreamTransactionHash.Count()));
|
||||||
self->ResumeRecv();
|
self->ResumeRecv();
|
||||||
self->ResetDownstreamState();
|
self->ResetDownstreamState();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -202,6 +202,10 @@ private:
|
|||||||
nsAutoPtr<SpdyStream2> &,
|
nsAutoPtr<SpdyStream2> &,
|
||||||
void *);
|
void *);
|
||||||
|
|
||||||
|
static PLDHashOperator GoAwayEnumerator(nsAHttpTransaction *,
|
||||||
|
nsAutoPtr<SpdyStream2> &,
|
||||||
|
void *);
|
||||||
|
|
||||||
// This is intended to be nsHttpConnectionMgr:nsHttpConnectionHandle taken
|
// This is intended to be nsHttpConnectionMgr:nsHttpConnectionHandle taken
|
||||||
// from the first transaction on this session. That object contains the
|
// from the first transaction on this session. That object contains the
|
||||||
// pointer to the real network-level nsHttpConnection object.
|
// pointer to the real network-level nsHttpConnection object.
|
||||||
@ -335,6 +339,9 @@ private:
|
|||||||
PRIntervalTime mLastDataReadEpoch; // used for IdleTime()
|
PRIntervalTime mLastDataReadEpoch; // used for IdleTime()
|
||||||
PRIntervalTime mPingSentEpoch;
|
PRIntervalTime mPingSentEpoch;
|
||||||
uint32_t mNextPingID;
|
uint32_t mNextPingID;
|
||||||
|
|
||||||
|
// used as a temporary buffer while enumerating the stream hash during GoAway
|
||||||
|
nsDeque mGoAwayStreamsToRestart;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace mozilla::net
|
}} // namespace mozilla::net
|
||||||
|
@ -93,9 +93,12 @@ SpdySession3::ShutdownEnumerator(nsAHttpTransaction *key,
|
|||||||
|
|
||||||
// On a clean server hangup the server sets the GoAwayID to be the ID of
|
// On a clean server hangup the server sets the GoAwayID to be the ID of
|
||||||
// the last transaction it processed. If the ID of stream in the
|
// the last transaction it processed. If the ID of stream in the
|
||||||
// local session is greater than that it can safely be restarted because the
|
// local stream is greater than that it can safely be restarted because the
|
||||||
// server guarantees it was not partially processed.
|
// server guarantees it was not partially processed. Streams that have not
|
||||||
if (self->mCleanShutdown && (stream->StreamID() > self->mGoAwayID))
|
// registered an ID haven't actually been sent yet so they can always be
|
||||||
|
// restarted.
|
||||||
|
if (self->mCleanShutdown &&
|
||||||
|
(stream->StreamID() > self->mGoAwayID || !stream->HasRegisteredID()))
|
||||||
self->CloseStream(stream, NS_ERROR_NET_RESET); // can be restarted
|
self->CloseStream(stream, NS_ERROR_NET_RESET); // can be restarted
|
||||||
else
|
else
|
||||||
self->CloseStream(stream, NS_ERROR_ABORT);
|
self->CloseStream(stream, NS_ERROR_ABORT);
|
||||||
@ -103,6 +106,22 @@ SpdySession3::ShutdownEnumerator(nsAHttpTransaction *key,
|
|||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PLDHashOperator
|
||||||
|
SpdySession3::GoAwayEnumerator(nsAHttpTransaction *key,
|
||||||
|
nsAutoPtr<SpdyStream3> &stream,
|
||||||
|
void *closure)
|
||||||
|
{
|
||||||
|
SpdySession3 *self = static_cast<SpdySession3 *>(closure);
|
||||||
|
|
||||||
|
// these streams were not processed by the server and can be restarted.
|
||||||
|
// Do that after the enumerator completes to avoid the risk of
|
||||||
|
// a restart event re-entrantly modifying this hash.
|
||||||
|
if (stream->StreamID() > self->mGoAwayID || !stream->HasRegisteredID())
|
||||||
|
self->mGoAwayStreamsToRestart.Push(stream);
|
||||||
|
|
||||||
|
return PL_DHASH_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
SpdySession3::~SpdySession3()
|
SpdySession3::~SpdySession3()
|
||||||
{
|
{
|
||||||
LOG3(("SpdySession3::~SpdySession3 %p mDownstreamState=%X",
|
LOG3(("SpdySession3::~SpdySession3 %p mDownstreamState=%X",
|
||||||
@ -301,7 +320,6 @@ SpdySession3::AddStream(nsAHttpTransaction *aHttpTransaction,
|
|||||||
&mUpstreamZlib,
|
&mUpstreamZlib,
|
||||||
aPriority);
|
aPriority);
|
||||||
|
|
||||||
|
|
||||||
LOG3(("SpdySession3::AddStream session=%p stream=%p NextID=0x%X (tentative)",
|
LOG3(("SpdySession3::AddStream session=%p stream=%p NextID=0x%X (tentative)",
|
||||||
this, stream, mNextStreamID));
|
this, stream, mNextStreamID));
|
||||||
|
|
||||||
@ -1203,10 +1221,39 @@ SpdySession3::HandleGoAway(SpdySession3 *self)
|
|||||||
self->mGoAwayID =
|
self->mGoAwayID =
|
||||||
PR_ntohl(reinterpret_cast<uint32_t *>(self->mInputFrameBuffer.get())[2]);
|
PR_ntohl(reinterpret_cast<uint32_t *>(self->mInputFrameBuffer.get())[2]);
|
||||||
self->mCleanShutdown = true;
|
self->mCleanShutdown = true;
|
||||||
|
|
||||||
LOG3(("SpdySession3::HandleGoAway %p GOAWAY Last-Good-ID 0x%X status 0x%X\n",
|
// Find streams greater than the last-good ID and mark them for deletion
|
||||||
self, self->mGoAwayID,
|
// in the mGoAwayStreamsToRestart queue with the GoAwayEnumerator. They can
|
||||||
PR_ntohl(reinterpret_cast<uint32_t *>(self->mInputFrameBuffer.get())[3])));
|
// be restarted.
|
||||||
|
self->mStreamTransactionHash.Enumerate(GoAwayEnumerator, self);
|
||||||
|
|
||||||
|
// Process the streams marked for deletion and restart.
|
||||||
|
uint32_t size = self->mGoAwayStreamsToRestart.GetSize();
|
||||||
|
for (uint32_t count = 0; count < size; ++count) {
|
||||||
|
SpdyStream3 *stream =
|
||||||
|
static_cast<SpdyStream3 *>(self->mGoAwayStreamsToRestart.PopFront());
|
||||||
|
|
||||||
|
self->CloseStream(stream, NS_ERROR_NET_RESET);
|
||||||
|
if (stream->HasRegisteredID())
|
||||||
|
self->mStreamIDHash.Remove(stream->StreamID());
|
||||||
|
self->mStreamTransactionHash.Remove(stream->Transaction());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queued streams can also be deleted from this session and restarted
|
||||||
|
// in another one. (they were never sent on the network so they implicitly
|
||||||
|
// are not covered by the last-good id.
|
||||||
|
size = self->mQueuedStreams.GetSize();
|
||||||
|
for (uint32_t count = 0; count < size; ++count) {
|
||||||
|
SpdyStream3 *stream =
|
||||||
|
static_cast<SpdyStream3 *>(self->mQueuedStreams.PopFront());
|
||||||
|
self->CloseStream(stream, NS_ERROR_NET_RESET);
|
||||||
|
self->mStreamTransactionHash.Remove(stream->Transaction());
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG3(("SpdySession3::HandleGoAway %p GOAWAY Last-Good-ID 0x%X status 0x%X "
|
||||||
|
"live streams=%d\n", self, self->mGoAwayID,
|
||||||
|
PR_ntohl(reinterpret_cast<uint32_t *>(self->mInputFrameBuffer.get())[3]),
|
||||||
|
self->mStreamTransactionHash.Count()));
|
||||||
|
|
||||||
self->ResumeRecv();
|
self->ResumeRecv();
|
||||||
self->ResetDownstreamState();
|
self->ResetDownstreamState();
|
||||||
|
@ -213,6 +213,10 @@ private:
|
|||||||
nsAutoPtr<SpdyStream3> &,
|
nsAutoPtr<SpdyStream3> &,
|
||||||
void *);
|
void *);
|
||||||
|
|
||||||
|
static PLDHashOperator GoAwayEnumerator(nsAHttpTransaction *,
|
||||||
|
nsAutoPtr<SpdyStream3> &,
|
||||||
|
void *);
|
||||||
|
|
||||||
static PLDHashOperator UpdateServerRwinEnumerator(nsAHttpTransaction *,
|
static PLDHashOperator UpdateServerRwinEnumerator(nsAHttpTransaction *,
|
||||||
nsAutoPtr<SpdyStream3> &,
|
nsAutoPtr<SpdyStream3> &,
|
||||||
void *);
|
void *);
|
||||||
@ -346,6 +350,9 @@ private:
|
|||||||
PRIntervalTime mLastDataReadEpoch; // used for IdleTime()
|
PRIntervalTime mLastDataReadEpoch; // used for IdleTime()
|
||||||
PRIntervalTime mPingSentEpoch;
|
PRIntervalTime mPingSentEpoch;
|
||||||
uint32_t mNextPingID;
|
uint32_t mNextPingID;
|
||||||
|
|
||||||
|
// used as a temporary buffer while enumerating the stream hash during GoAway
|
||||||
|
nsDeque mGoAwayStreamsToRestart;
|
||||||
};
|
};
|
||||||
|
|
||||||
}} // namespace mozilla::net
|
}} // namespace mozilla::net
|
||||||
|
@ -41,6 +41,8 @@ public:
|
|||||||
mFullyOpen = 1;
|
mFullyOpen = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasRegisteredID() { return mStreamID != 0; }
|
||||||
|
|
||||||
nsAHttpTransaction *Transaction()
|
nsAHttpTransaction *Transaction()
|
||||||
{
|
{
|
||||||
return mTransaction;
|
return mTransaction;
|
||||||
@ -121,7 +123,7 @@ private:
|
|||||||
// The quanta upstream data frames are chopped into
|
// The quanta upstream data frames are chopped into
|
||||||
uint32_t mChunkSize;
|
uint32_t mChunkSize;
|
||||||
|
|
||||||
// Flag is set when all http request headers have been read
|
// Flag is set when all http request headers have been read and ID is stable
|
||||||
uint32_t mSynFrameComplete : 1;
|
uint32_t mSynFrameComplete : 1;
|
||||||
|
|
||||||
// Flag is set when the HTTP processor has more data to send
|
// Flag is set when the HTTP processor has more data to send
|
||||||
|
@ -40,6 +40,8 @@ public:
|
|||||||
mFullyOpen = 1;
|
mFullyOpen = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasRegisteredID() { return mStreamID != 0; }
|
||||||
|
|
||||||
nsAHttpTransaction *Transaction()
|
nsAHttpTransaction *Transaction()
|
||||||
{
|
{
|
||||||
return mTransaction;
|
return mTransaction;
|
||||||
@ -143,7 +145,7 @@ private:
|
|||||||
// The quanta upstream data frames are chopped into
|
// The quanta upstream data frames are chopped into
|
||||||
uint32_t mChunkSize;
|
uint32_t mChunkSize;
|
||||||
|
|
||||||
// Flag is set when all http request headers have been read
|
// Flag is set when all http request headers have been read and ID is stable
|
||||||
uint32_t mSynFrameComplete : 1;
|
uint32_t mSynFrameComplete : 1;
|
||||||
|
|
||||||
// Flag is set when the HTTP processor has more data to send
|
// Flag is set when the HTTP processor has more data to send
|
||||||
|
Loading…
Reference in New Issue
Block a user