mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-15 13:09:14 +00:00
bug 762162 - network.http.timeout-connection r=honzab
This commit is contained in:
parent
314a0f595f
commit
623040ca15
@ -868,6 +868,10 @@ pref("network.http.qos", 0);
|
||||
// connection.
|
||||
pref("network.http.connection-retry-timeout", 250);
|
||||
|
||||
// The number of seconds after sending initial SYN for an HTTP connection
|
||||
// to give up if the OS does not give up first
|
||||
pref("network.http.connection-timeout", 90);
|
||||
|
||||
// Disable IPv6 for backup connections to workaround problems about broken
|
||||
// IPv6 connectivity.
|
||||
pref("network.http.fast-fallback-to-IPv4", true);
|
||||
|
@ -1704,6 +1704,7 @@ void
|
||||
nsHttpConnectionMgr::StartedConnect()
|
||||
{
|
||||
mNumActiveConns++;
|
||||
ActivateTimeoutTick(); // likely disabled by RecvdConnect()
|
||||
}
|
||||
|
||||
void
|
||||
@ -2161,10 +2162,42 @@ nsHttpConnectionMgr::ReadTimeoutTickCB(const nsACString &key,
|
||||
LOG(("nsHttpConnectionMgr::ReadTimeoutTickCB() this=%p host=%s\n",
|
||||
self, ent->mConnInfo->Host()));
|
||||
|
||||
// first call the tick handler for each active connection
|
||||
PRIntervalTime now = PR_IntervalNow();
|
||||
for (PRUint32 index = 0; index < ent->mActiveConns.Length(); ++index)
|
||||
ent->mActiveConns[index]->ReadTimeoutTick(now);
|
||||
|
||||
// now check for any stalled half open sockets
|
||||
if (ent->mHalfOpens.Length()) {
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
double maxConnectTime = gHttpHandler->ConnectTimeout(); /* in milliseconds */
|
||||
|
||||
for (PRUint32 index = ent->mHalfOpens.Length(); index > 0; ) {
|
||||
index--;
|
||||
|
||||
nsHalfOpenSocket *half = ent->mHalfOpens[index];
|
||||
double delta = half->Duration(now);
|
||||
// If the socket has timed out, close it so the waiting transaction
|
||||
// will get the proper signal
|
||||
if (delta > maxConnectTime) {
|
||||
LOG(("Force timeout of half open to %s after %.2fms.\n",
|
||||
ent->mConnInfo->HashKey().get(), delta));
|
||||
if (half->SocketTransport())
|
||||
half->SocketTransport()->Close(NS_ERROR_NET_TIMEOUT);
|
||||
if (half->BackupTransport())
|
||||
half->BackupTransport()->Close(NS_ERROR_NET_TIMEOUT);
|
||||
}
|
||||
|
||||
// If this half open hangs around for 5 seconds after we've closed() it
|
||||
// then just abandon the socket.
|
||||
if (delta > maxConnectTime + 5000) {
|
||||
LOG(("Abandon half open to %s after %.2fms.\n",
|
||||
ent->mConnInfo->HashKey().get(), delta));
|
||||
half->Abandon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
@ -2301,17 +2334,8 @@ nsHttpConnectionMgr::nsHalfOpenSocket::~nsHalfOpenSocket()
|
||||
NS_ABORT_IF_FALSE(!mSynTimer, "syntimer not null");
|
||||
LOG(("Destroying nsHalfOpenSocket [this=%p]\n", this));
|
||||
|
||||
if (mEnt) {
|
||||
// A failure to create the transport object at all
|
||||
// will result in this not being present in the halfopen table
|
||||
// so ignore failures of RemoveElement()
|
||||
mEnt->mHalfOpens.RemoveElement(this);
|
||||
|
||||
// If there are no unconnected half opens left in the array, then
|
||||
// it is liekly that this dtor transitioned
|
||||
if (!mEnt->UnconnectedHalfOpens())
|
||||
gHttpHandler->ConnMgr()->ProcessPendingQForEntry(mEnt);
|
||||
}
|
||||
if (mEnt)
|
||||
mEnt->RemoveHalfOpen(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2496,9 +2520,21 @@ nsHttpConnectionMgr::nsHalfOpenSocket::Abandon()
|
||||
|
||||
CancelBackupTimer();
|
||||
|
||||
if (mEnt)
|
||||
mEnt->RemoveHalfOpen(this);
|
||||
mEnt = nsnull;
|
||||
}
|
||||
|
||||
double
|
||||
nsHttpConnectionMgr::nsHalfOpenSocket::Duration(mozilla::TimeStamp epoch)
|
||||
{
|
||||
if (mPrimarySynStarted.IsNull())
|
||||
return 0;
|
||||
|
||||
return (epoch - mPrimarySynStarted).ToMilliseconds();
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP // method for nsITimerCallback
|
||||
nsHttpConnectionMgr::nsHalfOpenSocket::Notify(nsITimer *timer)
|
||||
{
|
||||
@ -3023,3 +3059,17 @@ nsHttpConnectionMgr::nsConnectionEntry::UnconnectedHalfOpens()
|
||||
}
|
||||
return unconnectedHalfOpens;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionMgr::
|
||||
nsConnectionEntry::RemoveHalfOpen(nsHalfOpenSocket *halfOpen)
|
||||
{
|
||||
// A failure to create the transport object at all
|
||||
// will result in it not being present in the halfopen table
|
||||
// so ignore failures of RemoveElement()
|
||||
mHalfOpens.RemoveElement(halfOpen);
|
||||
|
||||
if (!UnconnectedHalfOpens())
|
||||
// perhaps this reverted RestrictConnections()
|
||||
gHttpHandler->ConnMgr()->ProcessPendingQForEntry(this);
|
||||
}
|
||||
|
@ -265,6 +265,9 @@ private:
|
||||
// connection complete
|
||||
PRUint32 UnconnectedHalfOpens();
|
||||
|
||||
// Remove a particular half open socket from the mHalfOpens array
|
||||
void RemoveHalfOpen(nsHalfOpenSocket *);
|
||||
|
||||
// Pipeline depths for various states
|
||||
const static PRUint32 kPipelineUnlimited = 1024; // fully open - extended green
|
||||
const static PRUint32 kPipelineOpen = 6; // 6 on each conn - normal green
|
||||
@ -388,7 +391,10 @@ private:
|
||||
void SetupBackupTimer();
|
||||
void CancelBackupTimer();
|
||||
void Abandon();
|
||||
|
||||
double Duration(mozilla::TimeStamp epoch);
|
||||
nsISocketTransport *SocketTransport() { return mSocketTransport; }
|
||||
nsISocketTransport *BackupTransport() { return mBackupTransport; }
|
||||
|
||||
nsAHttpTransaction *Transaction() { return mTransaction; }
|
||||
|
||||
bool IsSpeculative() { return mSpeculative; }
|
||||
@ -580,8 +586,8 @@ private:
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
// A 1s tick to call nsHttpConnection::ReadTimeoutTick on
|
||||
// active http/1 connections. Disabled when there are no
|
||||
// active connections.
|
||||
// active http/1 connections and check for orphaned half opens.
|
||||
// Disabled when there are no active or half open connections.
|
||||
nsCOMPtr<nsITimer> mReadTimeoutTick;
|
||||
bool mReadTimeoutTickArmed;
|
||||
|
||||
|
@ -175,6 +175,7 @@ nsHttpHandler::nsHttpHandler()
|
||||
, mSpdySendingChunkSize(ASpdySession::kSendingChunkSize)
|
||||
, mSpdyPingThreshold(PR_SecondsToInterval(44))
|
||||
, mSpdyPingTimeout(PR_SecondsToInterval(8))
|
||||
, mConnectTimeout(90000)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
gHttpLog = PR_NewLogModule("nsHttp");
|
||||
@ -1107,6 +1108,15 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
||||
PR_SecondsToInterval((PRUint16) clamped(val, 0, 0x7fffffff));
|
||||
}
|
||||
|
||||
// The maximum amount of time to wait for socket transport to be
|
||||
// established
|
||||
if (PREF_CHANGED(HTTP_PREF("connection-timeout"))) {
|
||||
rv = prefs->GetIntPref(HTTP_PREF("connection-timeout"), &val);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
// the pref is in seconds, but the variable is in milliseconds
|
||||
mConnectTimeout = clamped(val, 1, 0xffff) * PR_MSEC_PER_SEC;
|
||||
}
|
||||
|
||||
// on transition of network.http.diagnostics to true print
|
||||
// a bunch of information to the console
|
||||
if (pref && PREF_CHANGED(HTTP_PREF("diagnostics"))) {
|
||||
|
@ -94,6 +94,7 @@ public:
|
||||
PRUint32 SpdySendingChunkSize() { return mSpdySendingChunkSize; }
|
||||
PRIntervalTime SpdyPingThreshold() { return mSpdyPingThreshold; }
|
||||
PRIntervalTime SpdyPingTimeout() { return mSpdyPingTimeout; }
|
||||
PRUint32 ConnectTimeout() { return mConnectTimeout; }
|
||||
|
||||
bool PromptTempRedirect() { return mPromptTempRedirect; }
|
||||
|
||||
@ -366,6 +367,10 @@ private:
|
||||
PRUint32 mSpdySendingChunkSize;
|
||||
PRIntervalTime mSpdyPingThreshold;
|
||||
PRIntervalTime mSpdyPingTimeout;
|
||||
|
||||
// The maximum amount of time to wait for socket transport to be
|
||||
// established. In milliseconds.
|
||||
PRUint32 mConnectTimeout;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user