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",
this, pollFlags));
if (mState == STATE_TRANSFERRING) {
// check poll flags for errors
if ((pollFlags & PR_POLL_ERR) ||
(pollFlags & PR_POLL_EXCEPT)) {
// the network connection was abruptly closed
mCondition = NS_ERROR_NET_RESET;
// check poll flags for errors
if ((pollFlags & PR_POLL_ERR) ||
(pollFlags & PR_POLL_EXCEPT)) {
// the network connection was abruptly closed
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) {
// the network connection was gracefully closed
mCondition = NS_BASE_STREAM_CLOSED;
}
else {
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);
}
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);
}
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) {

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

@ -113,7 +113,9 @@ nsSocketTransportService::PostEvent(nsISocketEventHandler *handler,
if (!mEventQ.mHead)
mEventQ.mHead = event;
PR_SetPollableEvent(mThreadEvent);
if (mThreadEvent)
PR_SetPollableEvent(mThreadEvent);
// else wait for Poll timeout
return NS_OK;
}
@ -223,6 +225,67 @@ nsSocketTransportService::RemoveFromIdleList(SocketContext *sock)
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
@ -329,11 +392,18 @@ nsSocketTransportService::Init()
if (!mThreadEvent) {
mThreadEvent = PR_NewPollableEvent();
//
// NOTE: per bug 190000, this failure could be caused by Zone-Alarm
// or similar software. Though this could also be a low-memory
// error, we'll treat it like being offline in the hopes of giving
// the user a better error message.
NS_ENSURE_TRUE(mThreadEvent, NS_ERROR_OFFLINE);
// or similar software.
//
// NOTE: per bug 191739, this failure could also be caused by lack
// 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);
@ -360,7 +430,9 @@ nsSocketTransportService::Shutdown()
// signal uninitialized to block further events
mInitialized = PR_FALSE;
PR_SetPollableEvent(mThreadEvent);
if (mThreadEvent)
PR_SetPollableEvent(mThreadEvent);
// else wait for Poll timeout
}
// join with thread
@ -425,10 +497,14 @@ nsSocketTransportService::Run()
//
// setup thread
//
NS_ASSERTION(mThreadEvent, "no thread event");
mPollList[0].fd = mThreadEvent;
mPollList[0].in_flags = PR_POLL_READ;
if (mThreadEvent) {
mPollList[0].fd = mThreadEvent;
mPollList[0].in_flags = PR_POLL_READ;
}
else {
mPollList[0].fd = nsnull;
mPollList[0].in_flags = 0;
}
PRInt32 i, count;
@ -486,16 +562,12 @@ nsSocketTransportService::Run()
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) {
LOG((" PR_Poll error [%d]\n", PR_GetError()));
active = PR_FALSE;
}
else if (n == 0) {
LOG((" PR_Poll timeout expired\n"));
// loop around again
}
else {
else if (n > 0) {
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) {
// grab the event queue
SocketEvent *head = nsnull, *event;
{
nsAutoLock lock(mEventQLock);
// wait should not block
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;
}
if (mPollList[0].out_flags == PR_POLL_READ)
active = ServiceEventQ();
}
else {
//
// service event queue whenever PR_Poll times out.
//
active = ServiceEventQ();
}
}

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

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