fixes bug 191739 "Browser does not work if loopback is disabled" r=dougt sr=bz a=asa

This commit is contained in:
darin%netscape.com 2003-02-06 21:20:26 +00:00
Родитель 5a26c66ccf
Коммит 7ef9daec3e
3 изменённых файлов: 124 добавлений и 72 удалений

Просмотреть файл

@ -1223,32 +1223,30 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, PRInt16 pollFlags)
LOG(("nsSocketTransport::OnSocketReady [this=%x pollflags=%hd]\n", LOG(("nsSocketTransport::OnSocketReady [this=%x pollflags=%hd]\n",
this, pollFlags)); this, pollFlags));
if (mState == STATE_TRANSFERRING) { // check poll flags for errors
// check poll flags for errors if ((pollFlags & PR_POLL_ERR) ||
if ((pollFlags & PR_POLL_ERR) || (pollFlags & PR_POLL_EXCEPT)) {
(pollFlags & PR_POLL_EXCEPT)) { // the network connection was abruptly closed
// the network connection was abruptly closed mCondition = NS_ERROR_NET_RESET;
mCondition = NS_ERROR_NET_RESET; }
else if (pollFlags & PR_POLL_HUP) {
// the network connection was gracefully closed
mCondition = NS_BASE_STREAM_CLOSED;
}
else if (mState == STATE_TRANSFERRING) {
if (pollFlags & PR_POLL_WRITE) {
SendStatus(STATUS_SENDING_TO);
// assume that we won't need to poll any longer (the stream will
// request that we poll again if it is still pending).
mPollFlags &= ~PR_POLL_WRITE;
mOutput.OnSocketReady(NS_OK);
} }
else if (pollFlags & PR_POLL_HUP) { if (pollFlags & PR_POLL_READ) {
// the network connection was gracefully closed SendStatus(STATUS_RECEIVING_FROM);
mCondition = NS_BASE_STREAM_CLOSED; // assume that we won't need to poll any longer (the stream will
} // request that we poll again if it is still pending).
else { mPollFlags &= ~PR_POLL_READ;
if (pollFlags & PR_POLL_WRITE) { mInput.OnSocketReady(NS_OK);
SendStatus(STATUS_SENDING_TO);
// assume that we won't need to poll any longer (the stream will
// request that we poll again if it is still pending).
mPollFlags &= ~PR_POLL_WRITE;
mOutput.OnSocketReady(NS_OK);
}
if (pollFlags & PR_POLL_READ) {
SendStatus(STATUS_RECEIVING_FROM);
// assume that we won't need to poll any longer (the stream will
// request that we poll again if it is still pending).
mPollFlags &= ~PR_POLL_READ;
mInput.OnSocketReady(NS_OK);
}
} }
} }
else if (mState == STATE_CONNECTING) { else if (mState == STATE_CONNECTING) {

Просмотреть файл

@ -113,7 +113,9 @@ nsSocketTransportService::PostEvent(nsISocketEventHandler *handler,
if (!mEventQ.mHead) if (!mEventQ.mHead)
mEventQ.mHead = event; mEventQ.mHead = event;
PR_SetPollableEvent(mThreadEvent); if (mThreadEvent)
PR_SetPollableEvent(mThreadEvent);
// else wait for Poll timeout
return NS_OK; return NS_OK;
} }
@ -223,6 +225,67 @@ nsSocketTransportService::RemoveFromIdleList(SocketContext *sock)
LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount)); LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
} }
PRInt32
nsSocketTransportService::Poll()
{
PRPollDesc *pollList;
PRUint32 pollCount;
PRIntervalTime pollTimeout;
if (mPollList[0].fd) {
pollList = mPollList;
pollCount = PollCount();
pollTimeout = NS_SOCKET_POLL_TIMEOUT;
}
else {
// no pollable event, so busy wait...
pollCount = PollCount() - 1;
if (pollCount)
pollList = &mPollList[1];
else
pollList = nsnull;
pollTimeout = PR_MillisecondsToInterval(25);
}
return PR_Poll(pollList, pollCount, pollTimeout);
}
PRBool
nsSocketTransportService::ServiceEventQ()
{
PRBool keepGoing;
// grab the event queue
SocketEvent *head = nsnull, *event;
{
nsAutoLock lock(mEventQLock);
// wait should not block
if (mThreadEvent)
PR_WaitForPollableEvent(mThreadEvent);
head = mEventQ.mHead;
mEventQ.mHead = nsnull;
mEventQ.mTail = nsnull;
// check to see if we're supposed to shutdown
keepGoing = mInitialized;
}
// service the event queue
mServicingEventQ = PR_TRUE;
while (head) {
head->mHandler->OnSocketEvent(head->mType,
head->mUparam,
head->mVparam);
// delete head of queue
event = head->mNext;
delete head;
head = event;
}
mServicingEventQ = PR_FALSE;
return keepGoing;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// host:port -> ipaddr cache // host:port -> ipaddr cache
@ -329,11 +392,18 @@ nsSocketTransportService::Init()
if (!mThreadEvent) { if (!mThreadEvent) {
mThreadEvent = PR_NewPollableEvent(); mThreadEvent = PR_NewPollableEvent();
//
// NOTE: per bug 190000, this failure could be caused by Zone-Alarm // NOTE: per bug 190000, this failure could be caused by Zone-Alarm
// or similar software. Though this could also be a low-memory // or similar software.
// error, we'll treat it like being offline in the hopes of giving //
// the user a better error message. // NOTE: per bug 191739, this failure could also be caused by lack
NS_ENSURE_TRUE(mThreadEvent, NS_ERROR_OFFLINE); // of a loopback device on Windows and OS/2 platforms (NSPR creates
// a loopback socket pair on these platforms to implement a pollable
// event object). if we can't create a pollable event, then we'll
// have to "busy wait" to implement the socket event queue :-(
//
NS_WARN_IF_FALSE(mThreadEvent,
"running socket transport thread without a pollable event");
} }
nsresult rv = NS_NewThread(&mThread, this, 0, PR_JOINABLE_THREAD); nsresult rv = NS_NewThread(&mThread, this, 0, PR_JOINABLE_THREAD);
@ -360,7 +430,9 @@ nsSocketTransportService::Shutdown()
// signal uninitialized to block further events // signal uninitialized to block further events
mInitialized = PR_FALSE; mInitialized = PR_FALSE;
PR_SetPollableEvent(mThreadEvent); if (mThreadEvent)
PR_SetPollableEvent(mThreadEvent);
// else wait for Poll timeout
} }
// join with thread // join with thread
@ -425,10 +497,14 @@ nsSocketTransportService::Run()
// //
// setup thread // setup thread
// //
NS_ASSERTION(mThreadEvent, "no thread event"); if (mThreadEvent) {
mPollList[0].fd = mThreadEvent;
mPollList[0].fd = mThreadEvent; mPollList[0].in_flags = PR_POLL_READ;
mPollList[0].in_flags = PR_POLL_READ; }
else {
mPollList[0].fd = nsnull;
mPollList[0].in_flags = 0;
}
PRInt32 i, count; PRInt32 i, count;
@ -486,16 +562,12 @@ nsSocketTransportService::Run()
LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount)); LOG((" calling PR_Poll [active=%u idle=%u]\n", mActiveCount, mIdleCount));
PRInt32 n = PR_Poll(mPollList, PollCount(), NS_SOCKET_POLL_TIMEOUT); PRInt32 n = Poll();
if (n < 0) { if (n < 0) {
LOG((" PR_Poll error [%d]\n", PR_GetError())); LOG((" PR_Poll error [%d]\n", PR_GetError()));
active = PR_FALSE; active = PR_FALSE;
} }
else if (n == 0) { else if (n > 0) {
LOG((" PR_Poll timeout expired\n"));
// loop around again
}
else {
count = PollCount(); count = PollCount();
// //
@ -519,38 +591,16 @@ nsSocketTransportService::Run()
} }
// //
// service the event queue // service the event queue (mPollList[0].fd == mThreadEvent)
// //
if (mPollList[0].out_flags == PR_POLL_READ) { if (mPollList[0].out_flags == PR_POLL_READ)
active = ServiceEventQ();
// grab the event queue }
SocketEvent *head = nsnull, *event; else {
{ //
nsAutoLock lock(mEventQLock); // service event queue whenever PR_Poll times out.
//
// wait should not block active = ServiceEventQ();
PR_WaitForPollableEvent(mPollList[0].fd);
head = mEventQ.mHead;
mEventQ.mHead = nsnull;
mEventQ.mTail = nsnull;
// check to see if we're supposed to shutdown
active = mInitialized;
}
// service the event queue
mServicingEventQ = PR_TRUE;
while (head) {
head->mHandler->OnSocketEvent(head->mType,
head->mUparam,
head->mVparam);
// delete head of queue
event = head->mNext;
delete head;
head = event;
}
mServicingEventQ = PR_FALSE;
}
} }
} }

Просмотреть файл

@ -231,6 +231,9 @@ private:
RemoveFromIdleList(sock); RemoveFromIdleList(sock);
return AddToPollList(sock); return AddToPollList(sock);
} }
// returns PR_FALSE to stop processing the main loop
PRBool ServiceEventQ();
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// poll list (socket thread only) // poll list (socket thread only)
@ -241,6 +244,7 @@ private:
PRPollDesc mPollList[ NS_SOCKET_MAX_COUNT + 1 ]; PRPollDesc mPollList[ NS_SOCKET_MAX_COUNT + 1 ];
PRUint32 PollCount() { return mActiveCount + 1; } PRUint32 PollCount() { return mActiveCount + 1; }
PRInt32 Poll(); // calls PR_Poll
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// mHostDB maps host:port -> nsHostEntry // mHostDB maps host:port -> nsHostEntry