зеркало из https://github.com/mozilla/gecko-dev.git
fixes bug 191739 "Browser does not work if loopback is disabled" r=dougt sr=bz a=asa
This commit is contained in:
Родитель
5a26c66ccf
Коммит
7ef9daec3e
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче