зеркало из 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;
|
SpdyStream31 *stream = mInputFrameDataStream;
|
||||||
mSegmentWriter = writer;
|
mSegmentWriter = writer;
|
||||||
rv = mInputFrameDataStream->WriteSegments(this, count, countWritten);
|
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;
|
mSegmentWriter = nullptr;
|
||||||
|
|
||||||
mLastDataReadEpoch = mLastReadEpoch;
|
mLastDataReadEpoch = mLastReadEpoch;
|
||||||
|
@ -2137,10 +2144,13 @@ SpdySession31::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
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
|
// maybe just blocked reading from network
|
||||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK)
|
if ((rv == NS_BASE_STREAM_WOULD_BLOCK) && !channelPipeFull) {
|
||||||
rv = NS_OK;
|
rv = NS_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -229,6 +229,13 @@ SpdyStream31::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SpdyStream31::ChannelPipeFull()
|
||||||
|
{
|
||||||
|
nsHttpTransaction *trans = mTransaction ? mTransaction->QueryHttpTransaction() : nullptr;
|
||||||
|
return trans ? trans->ChannelPipeFull() : false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpdyStream31::CreatePushHashKey(const nsCString &scheme,
|
SpdyStream31::CreatePushHashKey(const nsCString &scheme,
|
||||||
const nsCString &hostHeader,
|
const nsCString &hostHeader,
|
||||||
|
|
|
@ -88,6 +88,7 @@ public:
|
||||||
int64_t LocalWindow() { return mLocalWindow; }
|
int64_t LocalWindow() { return mLocalWindow; }
|
||||||
|
|
||||||
bool BlockedOnRwin() { return mBlockedOnRwin; }
|
bool BlockedOnRwin() { return mBlockedOnRwin; }
|
||||||
|
bool ChannelPipeFull();
|
||||||
|
|
||||||
// A pull stream has an implicit sink, a pushed stream has a sink
|
// A pull stream has an implicit sink, a pushed stream has a sink
|
||||||
// once it is matched to a pull stream.
|
// once it is matched to a pull stream.
|
||||||
|
|
|
@ -1765,23 +1765,27 @@ nsHttpConnection::OnSocketReadable()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mSocketInCondition = NS_OK;
|
||||||
rv = mTransaction->WriteSegments(this, nsIOService::gDefaultSegmentSize, &n);
|
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 (NS_FAILED(rv)) {
|
||||||
// if the transaction didn't want to take any more data, then
|
// if the transaction didn't want to take any more data, then
|
||||||
// wait for the transaction to call ResumeRecv.
|
// wait for the transaction to call ResumeRecv.
|
||||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK)
|
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||||
rv = NS_OK;
|
rv = NS_OK;
|
||||||
|
}
|
||||||
again = false;
|
again = false;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
mCurrentBytesRead += n;
|
mCurrentBytesRead += n;
|
||||||
mTotalBytesRead += n;
|
mTotalBytesRead += n;
|
||||||
if (NS_FAILED(mSocketInCondition)) {
|
if (NS_FAILED(mSocketInCondition)) {
|
||||||
// continue waiting for the socket if necessary...
|
// continue waiting for the socket if necessary...
|
||||||
if (mSocketInCondition == NS_BASE_STREAM_WOULD_BLOCK)
|
if (mSocketInCondition == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||||
rv = ResumeRecv();
|
rv = ResumeRecv();
|
||||||
else
|
} else {
|
||||||
rv = mSocketInCondition;
|
rv = mSocketInCondition;
|
||||||
|
}
|
||||||
again = false;
|
again = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,7 @@ nsHttpTransaction::nsHttpTransaction()
|
||||||
, mContentDecoding(false)
|
, mContentDecoding(false)
|
||||||
, mContentDecodingCheck(false)
|
, mContentDecodingCheck(false)
|
||||||
, mDeferredSendProgress(false)
|
, mDeferredSendProgress(false)
|
||||||
|
, mWaitingOnPipeOut(false)
|
||||||
, mReportedStart(false)
|
, mReportedStart(false)
|
||||||
, mReportedResponseHeader(false)
|
, mReportedResponseHeader(false)
|
||||||
, mForTakeResponseHead(nullptr)
|
, mForTakeResponseHead(nullptr)
|
||||||
|
@ -832,9 +833,10 @@ nsHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
|
||||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||||
nsCOMPtr<nsIEventTarget> target;
|
nsCOMPtr<nsIEventTarget> target;
|
||||||
gHttpHandler->GetSocketThreadTarget(getter_AddRefs(target));
|
gHttpHandler->GetSocketThreadTarget(getter_AddRefs(target));
|
||||||
if (target)
|
if (target) {
|
||||||
mPipeOut->AsyncWait(this, 0, 0, target);
|
mPipeOut->AsyncWait(this, 0, 0, target);
|
||||||
else {
|
mWaitingOnPipeOut = true;
|
||||||
|
} else {
|
||||||
NS_ERROR("no socket thread event target");
|
NS_ERROR("no socket thread event target");
|
||||||
rv = NS_ERROR_UNEXPECTED;
|
rv = NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
@ -2179,6 +2181,7 @@ NS_IMPL_QUERY_INTERFACE(nsHttpTransaction,
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHttpTransaction::OnInputStreamReady(nsIAsyncInputStream *out)
|
nsHttpTransaction::OnInputStreamReady(nsIAsyncInputStream *out)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||||
if (mConnection) {
|
if (mConnection) {
|
||||||
mConnection->TransactionHasDataToWrite(this);
|
mConnection->TransactionHasDataToWrite(this);
|
||||||
nsresult rv = mConnection->ResumeSend();
|
nsresult rv = mConnection->ResumeSend();
|
||||||
|
@ -2196,6 +2199,8 @@ nsHttpTransaction::OnInputStreamReady(nsIAsyncInputStream *out)
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsHttpTransaction::OnOutputStreamReady(nsIAsyncOutputStream *out)
|
nsHttpTransaction::OnOutputStreamReady(nsIAsyncOutputStream *out)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||||
|
mWaitingOnPipeOut = false;
|
||||||
if (mConnection) {
|
if (mConnection) {
|
||||||
mConnection->TransactionHasDataToRecv(this);
|
mConnection->TransactionHasDataToRecv(this);
|
||||||
nsresult rv = mConnection->ResumeRecv();
|
nsresult rv = mConnection->ResumeRecv();
|
||||||
|
|
|
@ -143,6 +143,7 @@ public:
|
||||||
}
|
}
|
||||||
void SetPushedStream(Http2PushedStream *push) { mPushedStream = push; }
|
void SetPushedStream(Http2PushedStream *push) { mPushedStream = push; }
|
||||||
uint32_t InitialRwin() const { return mInitialRwin; };
|
uint32_t InitialRwin() const { return mInitialRwin; };
|
||||||
|
bool ChannelPipeFull() { return mWaitingOnPipeOut; }
|
||||||
|
|
||||||
// Locked methods to get and set timing info
|
// Locked methods to get and set timing info
|
||||||
const TimingStruct Timings();
|
const TimingStruct Timings();
|
||||||
|
@ -306,6 +307,7 @@ private:
|
||||||
bool mContentDecoding;
|
bool mContentDecoding;
|
||||||
bool mContentDecodingCheck;
|
bool mContentDecodingCheck;
|
||||||
bool mDeferredSendProgress;
|
bool mDeferredSendProgress;
|
||||||
|
bool mWaitingOnPipeOut;
|
||||||
|
|
||||||
// mClosed := transaction has been explicitly closed
|
// mClosed := transaction has been explicitly closed
|
||||||
// mTransactionDone := transaction ran to completion or was interrupted
|
// mTransactionDone := transaction ran to completion or was interrupted
|
||||||
|
|
Загрузка…
Ссылка в новой задаче