fixes bug 192207 "M130B Trunk crash [@ 0x00000000 - PL_DHashTableOperate] (really in nsSocketTransportService::RememberHost)" r=dougt sr=brendan

git-svn-id: svn://10.0.0.236/trunk@138279 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
darin%netscape.com 2003-02-23 05:07:34 +00:00
parent a74a58a93d
commit 95fbdfee9d
2 changed files with 109 additions and 108 deletions

View File

@ -127,22 +127,20 @@ nsSocketTransportService::AttachSocket(PRFileDesc *fd, nsASocketHandler *handler
{
LOG(("nsSocketTransportService::AttachSocket [handler=%x]\n", handler));
NS_ENSURE_TRUE(mServicingEventQ, NS_ERROR_UNEXPECTED);
NS_ENSURE_TRUE(mIdleCount < NS_SOCKET_MAX_COUNT, NS_ERROR_UNEXPECTED);
SocketContext sock;
sock.mFD = fd;
sock.mHandler = handler;
SocketContext *sock = &mIdleList[mIdleCount];
sock->mFD = fd;
sock->mHandler = handler;
NS_ADDREF(handler);
mIdleCount++;
return NS_OK;
nsresult rv = AddToIdleList(&sock);
if (NS_SUCCEEDED(rv))
NS_ADDREF(handler);
return rv;
}
nsresult
nsSocketTransportService::DetachSocket_Internal(SocketContext *sock)
nsSocketTransportService::DetachSocket(SocketContext *sock)
{
LOG(("nsSocketTransportService::DetachSocket_Internal [handler=%x]\n", sock->mHandler));
LOG(("nsSocketTransportService::DetachSocket [handler=%x]\n", sock->mHandler));
// inform the handler that this socket is going away
sock->mHandler->OnSocketDetached(sock->mFD);
@ -151,9 +149,9 @@ nsSocketTransportService::DetachSocket_Internal(SocketContext *sock)
sock->mFD = nsnull;
NS_RELEASE(sock->mHandler);
// find out what list this is on...
PRInt32 index = sock - mActiveList;
if (index > 0 && index <= NS_SOCKET_MAX_COUNT)
// find out what list this is on.
PRUint32 index = sock - mActiveList;
if (index < NS_SOCKET_MAX_COUNT)
RemoveFromPollList(sock);
else
RemoveFromIdleList(sock);
@ -167,9 +165,14 @@ nsSocketTransportService::AddToPollList(SocketContext *sock)
{
LOG(("nsSocketTransportService::AddToPollList [handler=%x]\n", sock->mHandler));
NS_ASSERTION(mActiveCount < NS_SOCKET_MAX_COUNT, "too many active sockets");
if (mActiveCount == NS_SOCKET_MAX_COUNT) {
NS_ERROR("too many active sockets");
return NS_ERROR_UNEXPECTED;
}
mActiveList[mActiveCount] = *sock;
mActiveCount++;
memcpy(&mActiveList[++mActiveCount], sock, sizeof(SocketContext));
mPollList[mActiveCount].fd = sock->mFD;
mPollList[mActiveCount].in_flags = sock->mHandler->mPollFlags;
mPollList[mActiveCount].out_flags = 0;
@ -184,13 +187,13 @@ nsSocketTransportService::RemoveFromPollList(SocketContext *sock)
LOG(("nsSocketTransportService::RemoveFromPollList [handler=%x]\n", sock->mHandler));
PRUint32 index = sock - mActiveList;
NS_ASSERTION(index > 0 && index <= NS_SOCKET_MAX_COUNT, "invalid index");
NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index");
LOG((" index=%u mActiveCount=%u\n", index, mActiveCount));
if (index != mActiveCount) {
memcpy(&mActiveList[index], &mActiveList[mActiveCount], sizeof(SocketContext));
memcpy(&mPollList[index], &mPollList[mActiveCount], sizeof(PRPollDesc));
if (index != mActiveCount-1) {
mActiveList[index] = mActiveList[mActiveCount-1];
mPollList[index+1] = mPollList[mActiveCount];
}
mActiveCount--;
@ -202,8 +205,12 @@ nsSocketTransportService::AddToIdleList(SocketContext *sock)
{
LOG(("nsSocketTransportService::AddToIdleList [handler=%x]\n", sock->mHandler));
NS_ASSERTION(mIdleCount < NS_SOCKET_MAX_COUNT, "too many idle sockets");
memcpy(&mIdleList[mIdleCount], sock, sizeof(SocketContext));
if (mIdleCount == NS_SOCKET_MAX_COUNT) {
NS_ERROR("too many idle sockets");
return NS_ERROR_UNEXPECTED;
}
mIdleList[mIdleCount] = *sock;
mIdleCount++;
LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
@ -215,16 +222,36 @@ nsSocketTransportService::RemoveFromIdleList(SocketContext *sock)
{
LOG(("nsSocketTransportService::RemoveFromIdleList [handler=%x]\n", sock->mHandler));
PRInt32 index = sock - &mIdleList[0];
NS_ASSERTION(index >= 0 && index < NS_SOCKET_MAX_COUNT, "invalid index");
PRUint32 index = sock - &mIdleList[0];
NS_ASSERTION(index < NS_SOCKET_MAX_COUNT, "invalid index");
if (index != (PRInt32) mIdleCount - 1)
memcpy(&mIdleList[index], &mIdleList[mIdleCount - 1], sizeof(SocketContext));
if (index != mIdleCount-1)
mIdleList[index] = mIdleList[mIdleCount-1];
mIdleCount--;
LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
}
void
nsSocketTransportService::MoveToIdleList(SocketContext *sock)
{
nsresult rv = AddToIdleList(sock);
if (NS_FAILED(rv))
DetachSocket(sock);
else
RemoveFromPollList(sock);
}
void
nsSocketTransportService::MoveToPollList(SocketContext *sock)
{
nsresult rv = AddToPollList(sock);
if (NS_FAILED(rv))
DetachSocket(sock);
else
RemoveFromIdleList(sock);
}
PRInt32
nsSocketTransportService::Poll()
{
@ -233,13 +260,14 @@ nsSocketTransportService::Poll()
PRIntervalTime pollTimeout;
if (mPollList[0].fd) {
mPollList[0].out_flags = 0;
pollList = mPollList;
pollCount = PollCount();
pollCount = mActiveCount + 1;
pollTimeout = NS_SOCKET_POLL_TIMEOUT;
}
else {
// no pollable event, so busy wait...
pollCount = PollCount() - 1;
pollCount = mActiveCount;
if (pollCount)
pollList = &mPollList[1];
else
@ -268,7 +296,6 @@ nsSocketTransportService::ServiceEventQ()
keepGoing = mInitialized;
}
// service the event queue
mServicingEventQ = PR_TRUE;
while (head) {
head->mHandler->OnSocketEvent(head->mType,
head->mUparam,
@ -278,7 +305,6 @@ nsSocketTransportService::ServiceEventQ()
delete head;
head = event;
}
mServicingEventQ = PR_FALSE;
return keepGoing;
}
@ -491,16 +517,10 @@ nsSocketTransportService::Run()
PL_DHashTableInit(&mHostDB, &ops, nsnull, sizeof(nsHostEntry), 0);
//
// setup thread
// add thread event to poll list (mThreadEvent may be NULL)
//
if (mThreadEvent) {
mPollList[0].fd = mThreadEvent;
mPollList[0].in_flags = PR_POLL_READ;
}
else {
mPollList[0].fd = nsnull;
mPollList[0].in_flags = 0;
}
mPollList[0].fd = mThreadEvent;
mPollList[0].in_flags = PR_POLL_READ;
PRInt32 i, count;
@ -509,51 +529,44 @@ nsSocketTransportService::Run()
//
PRBool active = PR_TRUE;
while (active) {
// clear out flags for pollable event
mPollList[0].out_flags = 0;
//
// walk active list backwards to see if any sockets should actually be
// idle, then walk the idle list backwards to see if any idle sockets
// should become active. take care to only check idle sockets that
// should become active. take care to check only idle sockets that
// were idle to begin with ;-)
//
count = mIdleCount;
if (mActiveCount) {
for (i=mActiveCount; i>=1; --i) {
//---
LOG((" active [%d] { handler=%x condition=%x pollflags=%hu }\n", i,
mActiveList[i].mHandler,
mActiveList[i].mHandler->mCondition,
mActiveList[i].mHandler->mPollFlags));
//---
if (NS_FAILED(mActiveList[i].mHandler->mCondition))
DetachSocket_Internal(&mActiveList[i]);
for (i=mActiveCount-1; i>=0; --i) {
//---
LOG((" active [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
mActiveList[i].mHandler,
mActiveList[i].mHandler->mCondition,
mActiveList[i].mHandler->mPollFlags));
//---
if (NS_FAILED(mActiveList[i].mHandler->mCondition))
DetachSocket(&mActiveList[i]);
else {
PRUint16 in_flags = mActiveList[i].mHandler->mPollFlags;
if (in_flags == 0)
MoveToIdleList(&mActiveList[i]);
else {
PRUint16 in_flags = mActiveList[i].mHandler->mPollFlags;
if (in_flags == 0)
MoveToIdleList(&mActiveList[i]);
else {
// update poll flags
mPollList[i].in_flags = in_flags;
mPollList[i].out_flags = 0;
}
// update poll flags
mPollList[i+1].in_flags = in_flags;
mPollList[i+1].out_flags = 0;
}
}
}
if (count) {
for (i=count-1; i>=0; --i) {
//---
LOG((" idle [%d] { handler=%x condition=%x pollflags=%hu }\n", i,
mIdleList[i].mHandler,
mIdleList[i].mHandler->mCondition,
mIdleList[i].mHandler->mPollFlags));
//---
if (NS_FAILED(mIdleList[i].mHandler->mCondition))
DetachSocket_Internal(&mIdleList[i]);
else if (mIdleList[i].mHandler->mPollFlags != 0)
MoveToPollList(&mIdleList[i]);
}
for (i=count-1; i>=0; --i) {
//---
LOG((" idle [%u] { handler=%x condition=%x pollflags=%hu }\n", i,
mIdleList[i].mHandler,
mIdleList[i].mHandler->mCondition,
mIdleList[i].mHandler->mPollFlags));
//---
if (NS_FAILED(mIdleList[i].mHandler->mCondition))
DetachSocket(&mIdleList[i]);
else if (mIdleList[i].mHandler->mPollFlags != 0)
MoveToPollList(&mIdleList[i]);
}
LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount));
@ -564,16 +577,14 @@ nsSocketTransportService::Run()
active = PR_FALSE;
}
else if (n > 0) {
count = PollCount();
//
// service "active" sockets...
//
for (i=1; i<count; ++i) {
if (mPollList[i].out_flags != 0) {
for (i=0; i<PRInt32(mActiveCount); ++i) {
PRPollDesc &desc = mPollList[i+1];
if (desc.out_flags != 0) {
nsASocketHandler *handler = mActiveList[i].mHandler;
handler->OnSocketReady(mPollList[i].fd,
mPollList[i].out_flags);
handler->OnSocketReady(desc.fd, desc.out_flags);
}
}
@ -581,9 +592,9 @@ nsSocketTransportService::Run()
// check for "dead" sockets and remove them (need to do this in
// reverse order obviously).
//
for (i=count-1; i>=1; --i) {
for (i=mActiveCount-1; i>=0; --i) {
if (NS_FAILED(mActiveList[i].mHandler->mCondition))
DetachSocket_Internal(&mActiveList[i]);
DetachSocket(&mActiveList[i]);
}
//
@ -611,10 +622,10 @@ nsSocketTransportService::Run()
LOG(("shutting down socket transport thread...\n"));
// detach any sockets
for (i=mActiveCount; i>=1; --i)
DetachSocket_Internal(&mActiveList[i]);
for (i=mActiveCount-1; i>=0; --i)
DetachSocket(&mActiveList[i]);
for (i=mIdleCount-1; i>=0; --i)
DetachSocket_Internal(&mIdleList[i]);
DetachSocket(&mIdleList[i]);
// clear the hostname database
PL_DHashTableFinish(&mHostDB);

View File

@ -191,15 +191,16 @@ private:
SocketEventQ mEventQ;
PRLock *mEventQLock;
PRBool mServicingEventQ;
//-------------------------------------------------------------------------
// socket lists (socket thread only)
//
// only "active" sockets are on the poll list. the active list is kept
// in sync with the poll list such that the index of a socket on the poll
// list matches its index on the active socket list. as a result the first
// element of the active socket list is always null.
// in sync with the poll list such that:
//
// mActiveList[k].mFD == mPollList[k+1].fd
//
// where k=0,1,2,...
//-------------------------------------------------------------------------
struct SocketContext
@ -208,30 +209,19 @@ private:
nsASocketHandler *mHandler;
};
SocketContext mActiveList [ NS_SOCKET_MAX_COUNT + 1 ];
SocketContext mIdleList [ NS_SOCKET_MAX_COUNT ];
SocketContext mActiveList [ NS_SOCKET_MAX_COUNT ];
SocketContext mIdleList [ NS_SOCKET_MAX_COUNT ];
PRUint32 mActiveCount;
PRUint32 mIdleCount;
nsresult DetachSocket_Internal(SocketContext *);
nsresult DetachSocket(SocketContext *);
nsresult AddToIdleList(SocketContext *);
nsresult AddToPollList(SocketContext *);
void RemoveFromIdleList(SocketContext *);
void RemoveFromPollList(SocketContext *);
nsresult MoveToIdleList(SocketContext *sock)
{
nsresult rv = AddToIdleList(sock);
RemoveFromPollList(sock);
return rv;
}
nsresult MoveToPollList(SocketContext *sock)
{
nsresult rv = AddToPollList(sock);
RemoveFromIdleList(sock);
return rv;
}
void MoveToIdleList(SocketContext *sock);
void MoveToPollList(SocketContext *sock);
// returns PR_FALSE to stop processing the main loop
PRBool ServiceEventQ();
@ -239,13 +229,13 @@ private:
//-------------------------------------------------------------------------
// poll list (socket thread only)
//
// first element of the poll list is the "NSPR pollable event"
// first element of the poll list is mThreadEvent (or null if the pollable
// event cannot be created).
//-------------------------------------------------------------------------
PRPollDesc mPollList[ NS_SOCKET_MAX_COUNT + 1 ];
PRUint32 PollCount() { return mActiveCount + 1; }
PRInt32 Poll(); // calls PR_Poll
PRInt32 Poll(); // calls PR_Poll
//-------------------------------------------------------------------------
// mHostDB maps host:port -> nsHostEntry