зеркало из https://github.com/mozilla/gecko-dev.git
bug 1083930 - cpu spin during large h2/spdy upload r=hurley
--HG-- extra : rebase_source : 0204d5128df1f76d0e2c9a9ec24f719cb538a1e6
This commit is contained in:
Родитель
18bdfef857
Коммит
70c555d190
|
@ -83,6 +83,7 @@ nsHttpConnection::nsHttpConnection()
|
|||
, mTransactionCaps(0)
|
||||
, mResponseTimeoutEnabled(false)
|
||||
, mTCPKeepaliveConfig(kTCPKeepaliveDisabled)
|
||||
, mForceSendPending(false)
|
||||
{
|
||||
LOG(("Creating nsHttpConnection @%p\n", this));
|
||||
|
||||
|
@ -113,6 +114,10 @@ nsHttpConnection::~nsHttpConnection()
|
|||
Telemetry::HTTP_KBREAD_PER_CONN,
|
||||
totalKBRead);
|
||||
}
|
||||
if (mForceSendTimer) {
|
||||
mForceSendTimer->Cancel();
|
||||
mForceSendTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -569,6 +574,10 @@ nsHttpConnection::Close(nsresult reason)
|
|||
mTCPKeepaliveTransitionTimer->Cancel();
|
||||
mTCPKeepaliveTransitionTimer = nullptr;
|
||||
}
|
||||
if (mForceSendTimer) {
|
||||
mForceSendTimer->Cancel();
|
||||
mForceSendTimer = nullptr;
|
||||
}
|
||||
|
||||
if (NS_FAILED(reason)) {
|
||||
if (mIdleMonitoring)
|
||||
|
@ -1340,10 +1349,10 @@ nsHttpConnection::ResumeRecv()
|
|||
}
|
||||
|
||||
|
||||
class nsHttpConnectionForceIO : public nsRunnable
|
||||
class HttpConnectionForceIO : public nsRunnable
|
||||
{
|
||||
public:
|
||||
nsHttpConnectionForceIO(nsHttpConnection *aConn, bool doRecv)
|
||||
HttpConnectionForceIO(nsHttpConnection *aConn, bool doRecv)
|
||||
: mConn(aConn)
|
||||
, mDoRecv(doRecv)
|
||||
{}
|
||||
|
@ -1357,8 +1366,12 @@ public:
|
|||
return NS_OK;
|
||||
return mConn->OnInputStreamReady(mConn->mSocketIn);
|
||||
}
|
||||
if (!mConn->mSocketOut)
|
||||
|
||||
MOZ_ASSERT(mConn->mForceSendPending);
|
||||
mConn->mForceSendPending = false;
|
||||
if (!mConn->mSocketOut) {
|
||||
return NS_OK;
|
||||
}
|
||||
return mConn->OnOutputStreamReady(mConn->mSocketOut);
|
||||
}
|
||||
private:
|
||||
|
@ -1366,6 +1379,37 @@ private:
|
|||
bool mDoRecv;
|
||||
};
|
||||
|
||||
void
|
||||
nsHttpConnection::ForceSendIO(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
nsHttpConnection *self = static_cast<nsHttpConnection *>(aClosure);
|
||||
MOZ_ASSERT(aTimer == self->mForceSendTimer);
|
||||
self->mForceSendTimer = nullptr;
|
||||
NS_DispatchToCurrentThread(new HttpConnectionForceIO(self, false));
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHttpConnection::MaybeForceSendIO()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
// due to bug 1213084 sometimes real I/O events do not get serviced when
|
||||
// NSPR derived I/O events are ready and this can cause a deadlock with
|
||||
// https over https proxying. Normally we would expect the write callback to
|
||||
// be invoked before this timer goes off, but set it at the old windows
|
||||
// tick interval (kForceDelay) as a backup for those circumstances.
|
||||
static const uint32_t kForceDelay = 17; //ms
|
||||
|
||||
if (mForceSendPending) {
|
||||
return NS_OK;
|
||||
}
|
||||
MOZ_ASSERT(!mForceSendTimer);
|
||||
mForceSendPending = true;
|
||||
mForceSendTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
return mForceSendTimer->InitWithFuncCallback(
|
||||
nsHttpConnection::ForceSendIO, this, kForceDelay, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
// trigger an asynchronous read
|
||||
nsresult
|
||||
nsHttpConnection::ForceRecv()
|
||||
|
@ -1373,7 +1417,7 @@ nsHttpConnection::ForceRecv()
|
|||
LOG(("nsHttpConnection::ForceRecv [this=%p]\n", this));
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
return NS_DispatchToCurrentThread(new nsHttpConnectionForceIO(this, true));
|
||||
return NS_DispatchToCurrentThread(new HttpConnectionForceIO(this, true));
|
||||
}
|
||||
|
||||
// trigger an asynchronous write
|
||||
|
@ -1386,8 +1430,7 @@ nsHttpConnection::ForceSend()
|
|||
if (mTLSFilter) {
|
||||
return mTLSFilter->NudgeTunnel(this);
|
||||
}
|
||||
|
||||
return NS_DispatchToCurrentThread(new nsHttpConnectionForceIO(this, false));
|
||||
return MaybeForceSendIO();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2052,7 +2095,6 @@ nsHttpConnection::OnOutputStreamReady(nsIAsyncOutputStream *out)
|
|||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(out == mSocketOut, "unexpected socket");
|
||||
|
||||
// if the transaction was dropped...
|
||||
if (!mTransaction) {
|
||||
LOG((" no transaction; ignoring event\n"));
|
||||
|
|
|
@ -142,7 +142,7 @@ public:
|
|||
int64_t MaxBytesRead() {return mMaxBytesRead;}
|
||||
uint8_t GetLastHttpResponseVersion() { return mLastHttpResponseVersion; }
|
||||
|
||||
friend class nsHttpConnectionForceIO;
|
||||
friend class HttpConnectionForceIO;
|
||||
nsresult ForceSend();
|
||||
nsresult ForceRecv();
|
||||
|
||||
|
@ -349,6 +349,13 @@ private:
|
|||
// Flag to indicate connection is in inital keepalive period (fast detect).
|
||||
uint32_t mTCPKeepaliveConfig;
|
||||
nsCOMPtr<nsITimer> mTCPKeepaliveTransitionTimer;
|
||||
|
||||
private:
|
||||
// For ForceSend()
|
||||
static void ForceSendIO(nsITimer *aTimer, void *aClosure);
|
||||
nsresult MaybeForceSendIO();
|
||||
bool mForceSendPending;
|
||||
nsCOMPtr<nsITimer> mForceSendTimer;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
|
|
Загрузка…
Ссылка в новой задаче