Bug 1241906 - Spdy deadlock on suspended channel r=hurley

--HG--
extra : rebase_source : 5c61ce077ba3b6ff5e68b379ac0efda304424e1b
This commit is contained in:
Patrick McManus 2016-01-29 11:47:58 -05:00
Родитель 66e6da78e6
Коммит 677082b660
6 изменённых файлов: 38 добавлений и 9 удалений

Просмотреть файл

@ -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