зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1241906 - Spdy deadlock on suspended channel r=hurley
--HG-- extra : rebase_source : 5c61ce077ba3b6ff5e68b379ac0efda304424e1b
This commit is contained in:
Родитель
66e6da78e6
Коммит
677082b660
|
@ -2102,6 +2102,13 @@ SpdySession31::WriteSegments(nsAHttpSegmentWriter *writer,
|
|||
SpdyStream31 *stream = mInputFrameDataStream;
|
||||
mSegmentWriter = writer;
|
||||
rv = mInputFrameDataStream->WriteSegments(this, count, countWritten);
|
||||
bool channelPipeFull = false;
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
LOG3(("SpdySession31::WriteSegments session=%p stream=%p 0x%X "
|
||||
"stream channel pipe full\n",
|
||||
this, stream, stream ? stream->StreamID() : 0));
|
||||
channelPipeFull = mInputFrameDataStream->ChannelPipeFull();
|
||||
}
|
||||
mSegmentWriter = nullptr;
|
||||
|
||||
mLastDataReadEpoch = mLastReadEpoch;
|
||||
|
@ -2137,10 +2144,13 @@ SpdySession31::WriteSegments(nsAHttpSegmentWriter *writer,
|
|||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("SpdySession31 %p data frame read failure %x\n", this, rv));
|
||||
LOG3(("SpdySession31::WriteSegments session=%p stream=%p 0x%X "
|
||||
"data frame read failure %x pipefull=%d\n",
|
||||
this, stream, stream ? stream->StreamID() : 0, rv, channelPipeFull));
|
||||
// maybe just blocked reading from network
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK)
|
||||
if ((rv == NS_BASE_STREAM_WOULD_BLOCK) && !channelPipeFull) {
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
|
|
@ -229,6 +229,13 @@ SpdyStream31::WriteSegments(nsAHttpSegmentWriter *writer,
|
|||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
SpdyStream31::ChannelPipeFull()
|
||||
{
|
||||
nsHttpTransaction *trans = mTransaction ? mTransaction->QueryHttpTransaction() : nullptr;
|
||||
return trans ? trans->ChannelPipeFull() : false;
|
||||
}
|
||||
|
||||
void
|
||||
SpdyStream31::CreatePushHashKey(const nsCString &scheme,
|
||||
const nsCString &hostHeader,
|
||||
|
|
|
@ -88,6 +88,7 @@ public:
|
|||
int64_t LocalWindow() { return mLocalWindow; }
|
||||
|
||||
bool BlockedOnRwin() { return mBlockedOnRwin; }
|
||||
bool ChannelPipeFull();
|
||||
|
||||
// A pull stream has an implicit sink, a pushed stream has a sink
|
||||
// once it is matched to a pull stream.
|
||||
|
|
|
@ -1765,23 +1765,27 @@ nsHttpConnection::OnSocketReadable()
|
|||
break;
|
||||
}
|
||||
|
||||
mSocketInCondition = NS_OK;
|
||||
rv = mTransaction->WriteSegments(this, nsIOService::gDefaultSegmentSize, &n);
|
||||
LOG(("nsHttpConnection::OnSocketReadable %p trans->ws rv=%x n=%d socketin=%x\n",
|
||||
this, rv, n, mSocketInCondition));
|
||||
if (NS_FAILED(rv)) {
|
||||
// if the transaction didn't want to take any more data, then
|
||||
// wait for the transaction to call ResumeRecv.
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK)
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
rv = NS_OK;
|
||||
}
|
||||
again = false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
mCurrentBytesRead += n;
|
||||
mTotalBytesRead += n;
|
||||
if (NS_FAILED(mSocketInCondition)) {
|
||||
// continue waiting for the socket if necessary...
|
||||
if (mSocketInCondition == NS_BASE_STREAM_WOULD_BLOCK)
|
||||
if (mSocketInCondition == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
rv = ResumeRecv();
|
||||
else
|
||||
} else {
|
||||
rv = mSocketInCondition;
|
||||
}
|
||||
again = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ nsHttpTransaction::nsHttpTransaction()
|
|||
, mContentDecoding(false)
|
||||
, mContentDecodingCheck(false)
|
||||
, mDeferredSendProgress(false)
|
||||
, mWaitingOnPipeOut(false)
|
||||
, mReportedStart(false)
|
||||
, mReportedResponseHeader(false)
|
||||
, mForTakeResponseHead(nullptr)
|
||||
|
@ -832,9 +833,10 @@ nsHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
|
|||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
nsCOMPtr<nsIEventTarget> target;
|
||||
gHttpHandler->GetSocketThreadTarget(getter_AddRefs(target));
|
||||
if (target)
|
||||
if (target) {
|
||||
mPipeOut->AsyncWait(this, 0, 0, target);
|
||||
else {
|
||||
mWaitingOnPipeOut = true;
|
||||
} else {
|
||||
NS_ERROR("no socket thread event target");
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
@ -2179,6 +2181,7 @@ NS_IMPL_QUERY_INTERFACE(nsHttpTransaction,
|
|||
NS_IMETHODIMP
|
||||
nsHttpTransaction::OnInputStreamReady(nsIAsyncInputStream *out)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
if (mConnection) {
|
||||
mConnection->TransactionHasDataToWrite(this);
|
||||
nsresult rv = mConnection->ResumeSend();
|
||||
|
@ -2196,6 +2199,8 @@ nsHttpTransaction::OnInputStreamReady(nsIAsyncInputStream *out)
|
|||
NS_IMETHODIMP
|
||||
nsHttpTransaction::OnOutputStreamReady(nsIAsyncOutputStream *out)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
mWaitingOnPipeOut = false;
|
||||
if (mConnection) {
|
||||
mConnection->TransactionHasDataToRecv(this);
|
||||
nsresult rv = mConnection->ResumeRecv();
|
||||
|
|
|
@ -143,6 +143,7 @@ public:
|
|||
}
|
||||
void SetPushedStream(Http2PushedStream *push) { mPushedStream = push; }
|
||||
uint32_t InitialRwin() const { return mInitialRwin; };
|
||||
bool ChannelPipeFull() { return mWaitingOnPipeOut; }
|
||||
|
||||
// Locked methods to get and set timing info
|
||||
const TimingStruct Timings();
|
||||
|
@ -306,6 +307,7 @@ private:
|
|||
bool mContentDecoding;
|
||||
bool mContentDecodingCheck;
|
||||
bool mDeferredSendProgress;
|
||||
bool mWaitingOnPipeOut;
|
||||
|
||||
// mClosed := transaction has been explicitly closed
|
||||
// mTransactionDone := transaction ran to completion or was interrupted
|
||||
|
|
Загрузка…
Ссылка в новой задаче