mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-15 21:36:20 +00:00
bug 607741 - Raise max sockets open from 50 to up to 550. r=jduell
This commit is contained in:
parent
033ab28f8b
commit
fa9e2d5fa0
@ -64,6 +64,8 @@ nsSocketTransportService *gSocketTransportService = nsnull;
|
||||
PRThread *gSocketThread = nsnull;
|
||||
|
||||
#define SEND_BUFFER_PREF "network.tcp.sendbuffer"
|
||||
#define SOCKET_LIMIT_TARGET 550U
|
||||
#define SOCKET_LIMIT_MIN 50U
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ctor/dtor (called on the main/UI thread by the service manager)
|
||||
@ -75,6 +77,8 @@ nsSocketTransportService::nsSocketTransportService()
|
||||
, mLock("nsSocketTransportService::mLock")
|
||||
, mInitialized(PR_FALSE)
|
||||
, mShuttingDown(PR_FALSE)
|
||||
, mActiveListSize(SOCKET_LIMIT_MIN)
|
||||
, mIdleListSize(SOCKET_LIMIT_MIN)
|
||||
, mActiveCount(0)
|
||||
, mIdleCount(0)
|
||||
, mSendBufferSize(0)
|
||||
@ -85,6 +89,14 @@ nsSocketTransportService::nsSocketTransportService()
|
||||
|
||||
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
|
||||
|
||||
PR_CallOnce(&gMaxCountInitOnce, DiscoverMaxCount);
|
||||
mActiveList = (SocketContext *)
|
||||
moz_xmalloc(sizeof(SocketContext) * mActiveListSize);
|
||||
mIdleList = (SocketContext *)
|
||||
moz_xmalloc(sizeof(SocketContext) * mIdleListSize);
|
||||
mPollList = (PRPollDesc *)
|
||||
moz_xmalloc(sizeof(PRPollDesc) * (mActiveListSize + 1));
|
||||
|
||||
NS_ASSERTION(!gSocketTransportService, "must not instantiate twice");
|
||||
gSocketTransportService = this;
|
||||
}
|
||||
@ -97,6 +109,9 @@ nsSocketTransportService::~nsSocketTransportService()
|
||||
if (mThreadEvent)
|
||||
PR_DestroyPollableEvent(mThreadEvent);
|
||||
|
||||
moz_free(mActiveList);
|
||||
moz_free(mIdleList);
|
||||
moz_free(mPollList);
|
||||
gSocketTransportService = nsnull;
|
||||
}
|
||||
|
||||
@ -177,9 +192,11 @@ nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSocketTransportService::DetachSocket(SocketContext *sock)
|
||||
nsSocketTransportService::DetachSocket(SocketContext *listHead, SocketContext *sock)
|
||||
{
|
||||
SOCKET_LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler));
|
||||
NS_ABORT_IF_FALSE((listHead == mActiveList) || (listHead == mIdleList),
|
||||
"DetachSocket invalid head");
|
||||
|
||||
// inform the handler that this socket is going away
|
||||
sock->mHandler->OnSocketDetached(sock->mFD);
|
||||
@ -188,9 +205,7 @@ nsSocketTransportService::DetachSocket(SocketContext *sock)
|
||||
sock->mFD = nsnull;
|
||||
NS_RELEASE(sock->mHandler);
|
||||
|
||||
// find out what list this is on.
|
||||
PRUint32 index = sock - mActiveList;
|
||||
if (index < NS_SOCKET_MAX_COUNT)
|
||||
if (listHead == mActiveList)
|
||||
RemoveFromPollList(sock);
|
||||
else
|
||||
RemoveFromIdleList(sock);
|
||||
@ -211,13 +226,18 @@ nsSocketTransportService::DetachSocket(SocketContext *sock)
|
||||
nsresult
|
||||
nsSocketTransportService::AddToPollList(SocketContext *sock)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!(((PRUint32)(sock - mActiveList)) < mActiveListSize),
|
||||
"AddToPollList Socket Already Active");
|
||||
|
||||
SOCKET_LOG(("nsSocketTransportService::AddToPollList [handler=%x]\n", sock->mHandler));
|
||||
|
||||
if (mActiveCount == NS_SOCKET_MAX_COUNT) {
|
||||
NS_ERROR("too many active sockets");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
if (mActiveCount == mActiveListSize) {
|
||||
SOCKET_LOG((" Active List size of %d met\n", mActiveCount));
|
||||
if (!GrowActiveList()) {
|
||||
NS_ERROR("too many active sockets");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mActiveList[mActiveCount] = *sock;
|
||||
mActiveCount++;
|
||||
|
||||
@ -235,7 +255,7 @@ nsSocketTransportService::RemoveFromPollList(SocketContext *sock)
|
||||
SOCKET_LOG(("nsSocketTransportService::RemoveFromPollList [handler=%x]\n", sock->mHandler));
|
||||
|
||||
PRUint32 index = sock - mActiveList;
|
||||
NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index");
|
||||
NS_ABORT_IF_FALSE(index < mActiveListSize, "invalid index");
|
||||
|
||||
SOCKET_LOG((" index=%u mActiveCount=%u\n", index, mActiveCount));
|
||||
|
||||
@ -251,11 +271,16 @@ nsSocketTransportService::RemoveFromPollList(SocketContext *sock)
|
||||
nsresult
|
||||
nsSocketTransportService::AddToIdleList(SocketContext *sock)
|
||||
{
|
||||
SOCKET_LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler));
|
||||
NS_ABORT_IF_FALSE(!(((PRUint32)(sock - mIdleList)) < mIdleListSize),
|
||||
"AddToIdlelList Socket Already Idle");
|
||||
|
||||
if (mIdleCount == NS_SOCKET_MAX_COUNT) {
|
||||
NS_ERROR("too many idle sockets");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
SOCKET_LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler));
|
||||
if (mIdleCount == mIdleListSize) {
|
||||
SOCKET_LOG((" Idle List size of %d met\n", mIdleCount));
|
||||
if (!GrowIdleList()) {
|
||||
NS_ERROR("too many idle sockets");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
mIdleList[mIdleCount] = *sock;
|
||||
@ -270,8 +295,8 @@ nsSocketTransportService::RemoveFromIdleList(SocketContext *sock)
|
||||
{
|
||||
SOCKET_LOG(("nsSocketTransportService::RemoveFromIdleList [handler=%x]\n", sock->mHandler));
|
||||
|
||||
PRUint32 index = sock - &mIdleList[0];
|
||||
NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index");
|
||||
PRUint32 index = sock - mIdleList;
|
||||
NS_ASSERTION(index < mIdleListSize, "invalid index in idle list");
|
||||
|
||||
if (index != mIdleCount-1)
|
||||
mIdleList[index] = mIdleList[mIdleCount-1];
|
||||
@ -285,7 +310,7 @@ nsSocketTransportService::MoveToIdleList(SocketContext *sock)
|
||||
{
|
||||
nsresult rv = AddToIdleList(sock);
|
||||
if (NS_FAILED(rv))
|
||||
DetachSocket(sock);
|
||||
DetachSocket(mActiveList, sock);
|
||||
else
|
||||
RemoveFromPollList(sock);
|
||||
}
|
||||
@ -295,11 +320,43 @@ nsSocketTransportService::MoveToPollList(SocketContext *sock)
|
||||
{
|
||||
nsresult rv = AddToPollList(sock);
|
||||
if (NS_FAILED(rv))
|
||||
DetachSocket(sock);
|
||||
DetachSocket(mIdleList, sock);
|
||||
else
|
||||
RemoveFromIdleList(sock);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSocketTransportService::GrowActiveList()
|
||||
{
|
||||
PRInt32 toAdd = gMaxCount - mActiveListSize;
|
||||
if (toAdd > 100)
|
||||
toAdd = 100;
|
||||
if (toAdd < 1)
|
||||
return PR_FALSE;
|
||||
|
||||
mActiveListSize += toAdd;
|
||||
mActiveList = (SocketContext *)
|
||||
moz_xrealloc(mActiveList, sizeof(SocketContext) * mActiveListSize);
|
||||
mPollList = (PRPollDesc *)
|
||||
moz_xrealloc(mPollList, sizeof(PRPollDesc) * (mActiveListSize + 1));
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSocketTransportService::GrowIdleList()
|
||||
{
|
||||
PRInt32 toAdd = gMaxCount - mIdleListSize;
|
||||
if (toAdd > 100)
|
||||
toAdd = 100;
|
||||
if (toAdd < 1)
|
||||
return PR_FALSE;
|
||||
|
||||
mIdleListSize += toAdd;
|
||||
mIdleList = (SocketContext *)
|
||||
moz_xrealloc(mIdleList, sizeof(SocketContext) * mIdleListSize);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRIntervalTime
|
||||
nsSocketTransportService::PollTimeout()
|
||||
{
|
||||
@ -594,9 +651,9 @@ nsSocketTransportService::Run()
|
||||
// detach any sockets
|
||||
PRInt32 i;
|
||||
for (i=mActiveCount-1; i>=0; --i)
|
||||
DetachSocket(&mActiveList[i]);
|
||||
DetachSocket(mActiveList, &mActiveList[i]);
|
||||
for (i=mIdleCount-1; i>=0; --i)
|
||||
DetachSocket(&mIdleList[i]);
|
||||
DetachSocket(mIdleList, &mIdleList[i]);
|
||||
|
||||
// Final pass over the event queue. This makes sure that events posted by
|
||||
// socket detach handlers get processed.
|
||||
@ -635,7 +692,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait)
|
||||
mActiveList[i].mHandler->mPollFlags));
|
||||
//---
|
||||
if (NS_FAILED(mActiveList[i].mHandler->mCondition))
|
||||
DetachSocket(&mActiveList[i]);
|
||||
DetachSocket(mActiveList, &mActiveList[i]);
|
||||
else {
|
||||
PRUint16 in_flags = mActiveList[i].mHandler->mPollFlags;
|
||||
if (in_flags == 0)
|
||||
@ -655,7 +712,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait)
|
||||
mIdleList[i].mHandler->mPollFlags));
|
||||
//---
|
||||
if (NS_FAILED(mIdleList[i].mHandler->mCondition))
|
||||
DetachSocket(&mIdleList[i]);
|
||||
DetachSocket(mIdleList, &mIdleList[i]);
|
||||
else if (mIdleList[i].mHandler->mPollFlags != 0)
|
||||
MoveToPollList(&mIdleList[i]);
|
||||
}
|
||||
@ -702,7 +759,7 @@ nsSocketTransportService::DoPollIteration(PRBool wait)
|
||||
//
|
||||
for (i=mActiveCount-1; i>=0; --i) {
|
||||
if (NS_FAILED(mActiveList[i].mHandler->mCondition))
|
||||
DetachSocket(&mActiveList[i]);
|
||||
DetachSocket(mActiveList, &mActiveList[i]);
|
||||
}
|
||||
|
||||
if (n != 0 && mPollList[0].out_flags == PR_POLL_READ) {
|
||||
@ -771,3 +828,66 @@ nsSocketTransportService::GetSendBufferSize(PRInt32 *value)
|
||||
}
|
||||
|
||||
|
||||
/// ugly OS specific includes are placed at the bottom of the src for clarity
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include <windows.h>
|
||||
#elif defined(XP_UNIX) && !defined(AIX) && !defined(NEXTSTEP) && !defined(QNX)
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
PRStatus
|
||||
nsSocketTransportService::DiscoverMaxCount()
|
||||
{
|
||||
gMaxCount = SOCKET_LIMIT_MIN;
|
||||
|
||||
#if defined(XP_UNIX) && !defined(AIX) && !defined(NEXTSTEP) && !defined(QNX)
|
||||
// On unix and os x network sockets and file
|
||||
// descriptors are the same. OS X comes defaulted at 256,
|
||||
// most linux at 1000. We can reliably use [sg]rlimit to
|
||||
// query that and raise it. We will try to raise it 250 past
|
||||
// our target number of SOCKET_LIMIT_TARGET so that some descriptors
|
||||
// are still available for other things.
|
||||
|
||||
struct rlimit rlimitData;
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlimitData) == -1)
|
||||
return PR_SUCCESS;
|
||||
if (rlimitData.rlim_cur >= SOCKET_LIMIT_TARGET + 250) {
|
||||
gMaxCount = SOCKET_LIMIT_TARGET;
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
PRInt32 maxallowed = rlimitData.rlim_max;
|
||||
if (maxallowed == -1) { /* no limit */
|
||||
maxallowed = SOCKET_LIMIT_TARGET + 250;
|
||||
} else if ((PRUint32)maxallowed < SOCKET_LIMIT_MIN + 250) {
|
||||
return PR_SUCCESS;
|
||||
} else if ((PRUint32)maxallowed > SOCKET_LIMIT_TARGET + 250) {
|
||||
maxallowed = SOCKET_LIMIT_TARGET + 250;
|
||||
}
|
||||
|
||||
rlimitData.rlim_cur = maxallowed;
|
||||
setrlimit(RLIMIT_NOFILE, &rlimitData);
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlimitData) != -1)
|
||||
if (rlimitData.rlim_cur > SOCKET_LIMIT_MIN + 250)
|
||||
gMaxCount = rlimitData.rlim_cur - 250;
|
||||
|
||||
#elif defined(XP_WIN) && !defined(WIN_CE)
|
||||
// win 95, 98, etc had a limit of 100 - so we will just
|
||||
// use the historical 50 in every case older than XP (0x501).
|
||||
// >= XP is confirmed to have at least 1000
|
||||
|
||||
OSVERSIONINFO osInfo = { sizeof(OSVERSIONINFO) };
|
||||
if (GetVersionEx(&osInfo)) {
|
||||
PRInt32 version =
|
||||
(osInfo.dwMajorVersion & 0xff) << 8 |
|
||||
(osInfo.dwMinorVersion & 0xff);
|
||||
if (version >= 0x501) /* xp or later */
|
||||
gMaxCount = SOCKET_LIMIT_TARGET;
|
||||
}
|
||||
#else
|
||||
// other platforms are harder to test - so leave at safe legacy value
|
||||
#endif
|
||||
|
||||
return PR_SUCCESS;
|
||||
}
|
||||
|
@ -65,7 +65,6 @@ extern PRLogModuleInfo *gSocketTransportLog;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define NS_SOCKET_MAX_COUNT 50
|
||||
#define NS_SOCKET_POLL_TIMEOUT PR_INTERVAL_NO_TIMEOUT
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -89,6 +88,12 @@ public:
|
||||
|
||||
nsSocketTransportService();
|
||||
|
||||
// Max Socket count may need to get initialized/used by nsHttpHandler
|
||||
// before this class is initialized.
|
||||
static PRUint32 gMaxCount;
|
||||
static PRCallOnceType gMaxCountInitOnce;
|
||||
static PRStatus DiscoverMaxCount();
|
||||
|
||||
//
|
||||
// the number of sockets that can be attached at any given time is
|
||||
// limited. this is done because some operating systems (e.g., Win9x)
|
||||
@ -97,7 +102,7 @@ public:
|
||||
// call CanAttachSocket and check the result before creating a socket.
|
||||
//
|
||||
PRBool CanAttachSocket() {
|
||||
return mActiveCount + mIdleCount < NS_SOCKET_MAX_COUNT;
|
||||
return mActiveCount + mIdleCount < gMaxCount;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -153,19 +158,25 @@ private:
|
||||
PRUint16 mElapsedTime; // time elapsed w/o activity
|
||||
};
|
||||
|
||||
SocketContext mActiveList [ NS_SOCKET_MAX_COUNT ];
|
||||
SocketContext mIdleList [ NS_SOCKET_MAX_COUNT ];
|
||||
SocketContext *mActiveList; /* mListSize entries */
|
||||
SocketContext *mIdleList; /* mListSize entries */
|
||||
|
||||
PRUint32 mActiveListSize;
|
||||
PRUint32 mIdleListSize;
|
||||
PRUint32 mActiveCount;
|
||||
PRUint32 mIdleCount;
|
||||
|
||||
nsresult DetachSocket(SocketContext *);
|
||||
nsresult DetachSocket(SocketContext *, SocketContext *);
|
||||
nsresult AddToIdleList(SocketContext *);
|
||||
nsresult AddToPollList(SocketContext *);
|
||||
void RemoveFromIdleList(SocketContext *);
|
||||
void RemoveFromPollList(SocketContext *);
|
||||
void MoveToIdleList(SocketContext *sock);
|
||||
void MoveToPollList(SocketContext *sock);
|
||||
|
||||
PRBool GrowActiveList();
|
||||
PRBool GrowIdleList();
|
||||
void InitMaxCount();
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// poll list (socket thread only)
|
||||
@ -174,7 +185,7 @@ private:
|
||||
// event cannot be created).
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
PRPollDesc mPollList[ NS_SOCKET_MAX_COUNT + 1 ];
|
||||
PRPollDesc *mPollList; /* mListSize + 1 entries */
|
||||
|
||||
PRIntervalTime PollTimeout(); // computes ideal poll timeout
|
||||
nsresult DoPollIteration(PRBool wait);
|
||||
|
@ -844,7 +844,11 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
||||
if (PREF_CHANGED(HTTP_PREF("max-connections"))) {
|
||||
rv = prefs->GetIntPref(HTTP_PREF("max-connections"), &val);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mMaxConnections = (PRUint16) NS_CLAMP(val, 1, NS_SOCKET_MAX_COUNT);
|
||||
PR_CallOnce(&nsSocketTransportService::gMaxCountInitOnce,
|
||||
nsSocketTransportService::DiscoverMaxCount);
|
||||
mMaxConnections =
|
||||
(PRUint16) NS_CLAMP((PRUint32)val, 1,
|
||||
nsSocketTransportService::gMaxCount);
|
||||
if (mConnMgr)
|
||||
mConnMgr->UpdateParam(nsHttpConnectionMgr::MAX_CONNECTIONS,
|
||||
mMaxConnections);
|
||||
|
Loading…
x
Reference in New Issue
Block a user