mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out changeset efa0fb87773e (bug 698882) for failing xpcshell and xperf tests
This commit is contained in:
parent
f53414a463
commit
2197adfcc5
@ -1,275 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsSocketTransportService2.h"
|
||||
#include "PollableEvent.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "prerror.h"
|
||||
#include "prio.h"
|
||||
#include "private/pprio.h"
|
||||
#include "prnetdb.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "ShutdownLayer.h"
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#define USEPIPE 1
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
#ifndef USEPIPE
|
||||
static PRDescIdentity sPollableEventLayerIdentity;
|
||||
static PRIOMethods sPollableEventLayerMethods;
|
||||
static PRIOMethods *sPollableEventLayerMethodsPtr = nullptr;
|
||||
|
||||
static void LazyInitSocket()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
if (sPollableEventLayerMethodsPtr) {
|
||||
return;
|
||||
}
|
||||
sPollableEventLayerIdentity = PR_GetUniqueIdentity("PollableEvent Layer");
|
||||
sPollableEventLayerMethods = *PR_GetDefaultIOMethods();
|
||||
sPollableEventLayerMethodsPtr = &sPollableEventLayerMethods;
|
||||
}
|
||||
|
||||
static bool NewTCPSocketPair(PRFileDesc *fd[])
|
||||
{
|
||||
// this is a replacement for PR_NewTCPSocketPair that manually
|
||||
// sets the recv buffer to 64K. A windows bug (1248358)
|
||||
// can result in using an incompatible rwin and window
|
||||
// scale option on localhost pipes if not set before connect.
|
||||
|
||||
PRFileDesc *listener = nullptr;
|
||||
PRFileDesc *writer = nullptr;
|
||||
PRFileDesc *reader = nullptr;
|
||||
PRSocketOptionData recvBufferOpt;
|
||||
recvBufferOpt.option = PR_SockOpt_RecvBufferSize;
|
||||
recvBufferOpt.value.recv_buffer_size = 65535;
|
||||
|
||||
PRSocketOptionData nodelayOpt;
|
||||
nodelayOpt.option = PR_SockOpt_NoDelay;
|
||||
nodelayOpt.value.no_delay = true;
|
||||
|
||||
PRSocketOptionData noblockOpt;
|
||||
noblockOpt.option = PR_SockOpt_Nonblocking;
|
||||
noblockOpt.value.non_blocking = true;
|
||||
|
||||
listener = PR_OpenTCPSocket(PR_AF_INET);
|
||||
if (!listener) {
|
||||
goto failed;
|
||||
}
|
||||
PR_SetSocketOption(listener, &recvBufferOpt);
|
||||
PR_SetSocketOption(listener, &nodelayOpt);
|
||||
PR_SetSocketOption(listener, &noblockOpt);
|
||||
PRNetAddr listenAddr;
|
||||
memset(&listenAddr, 0, sizeof(listenAddr));
|
||||
if ((PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &listenAddr) == PR_FAILURE) ||
|
||||
(PR_Bind(listener, &listenAddr) == PR_FAILURE) ||
|
||||
(PR_GetSockName(listener, &listenAddr) == PR_FAILURE) || // learn the dynamic port
|
||||
(PR_Listen(listener, 5) == PR_FAILURE)) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
writer = PR_OpenTCPSocket(PR_AF_INET);
|
||||
if (!writer) {
|
||||
goto failed;
|
||||
}
|
||||
PR_SetSocketOption(writer, &recvBufferOpt);
|
||||
PR_SetSocketOption(writer, &nodelayOpt);
|
||||
PR_SetSocketOption(writer, &noblockOpt);
|
||||
PRNetAddr writerAddr;
|
||||
if (PR_InitializeNetAddr(PR_IpAddrLoopback, ntohs(listenAddr.inet.port), &writerAddr) == PR_FAILURE) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (PR_Connect(writer, &writerAddr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
|
||||
if ((PR_GetError() != PR_IN_PROGRESS_ERROR) ||
|
||||
(PR_ConnectContinue(writer, PR_POLL_WRITE) == PR_FAILURE)) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
reader = PR_Accept(listener, &listenAddr, PR_INTERVAL_NO_TIMEOUT);
|
||||
if (!reader) {
|
||||
goto failed;
|
||||
}
|
||||
PR_SetSocketOption(reader, &recvBufferOpt);
|
||||
PR_SetSocketOption(reader, &nodelayOpt);
|
||||
PR_SetSocketOption(reader, &noblockOpt);
|
||||
PR_Close(listener);
|
||||
|
||||
fd[0] = reader;
|
||||
fd[1] = writer;
|
||||
return true;
|
||||
|
||||
failed:
|
||||
if (listener) {
|
||||
PR_Close(listener);
|
||||
}
|
||||
if (reader) {
|
||||
PR_Close(reader);
|
||||
}
|
||||
if (writer) {
|
||||
PR_Close(writer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
PollableEvent::PollableEvent()
|
||||
: mWriteFD(nullptr)
|
||||
, mReadFD(nullptr)
|
||||
, mSignaled(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(PollableEvent);
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
// create pair of prfiledesc that can be used as a poll()ble
|
||||
// signal. on windows use a localhost socket pair, and on
|
||||
// unix use a pipe.
|
||||
#ifdef USEPIPE
|
||||
SOCKET_LOG(("PollableEvent() using pipe\n"));
|
||||
if (PR_CreatePipe(&mReadFD, &mWriteFD) == PR_SUCCESS) {
|
||||
// make the pipe non blocking. NSPR asserts at
|
||||
// trying to use SockOpt here
|
||||
PROsfd fd = PR_FileDesc2NativeHandle(mReadFD);
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
(void)fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
fd = PR_FileDesc2NativeHandle(mWriteFD);
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
(void)fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
} else {
|
||||
mReadFD = nullptr;
|
||||
mWriteFD = nullptr;
|
||||
SOCKET_LOG(("PollableEvent() pipe failed\n"));
|
||||
}
|
||||
#else
|
||||
SOCKET_LOG(("PollableEvent() using socket pair\n"));
|
||||
PRFileDesc *fd[2];
|
||||
LazyInitSocket();
|
||||
if (NewTCPSocketPair(fd)) {
|
||||
mReadFD = fd[0];
|
||||
mWriteFD = fd[1];
|
||||
|
||||
// compatibility with LSPs such as McAfee that assume a NSPR
|
||||
// layer for read ala the nspr Pollable Event - Bug 698882. This layer is a nop.
|
||||
PRFileDesc *topLayer =
|
||||
PR_CreateIOLayerStub(sPollableEventLayerIdentity,
|
||||
sPollableEventLayerMethodsPtr);
|
||||
if (topLayer) {
|
||||
if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, topLayer) == PR_FAILURE) {
|
||||
topLayer->dtor(topLayer);
|
||||
} else {
|
||||
SOCKET_LOG(("PollableEvent() nspr layer ok\n"));
|
||||
mReadFD = topLayer;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
SOCKET_LOG(("PollableEvent() socketpair failed\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mReadFD && mWriteFD) {
|
||||
// prime the system to deal with races invovled in [dc]tor cycle
|
||||
SOCKET_LOG(("PollableEvent() ctor ok\n"));
|
||||
mSignaled = true;
|
||||
PR_Write(mWriteFD, "I", 1);
|
||||
}
|
||||
}
|
||||
|
||||
PollableEvent::~PollableEvent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PollableEvent);
|
||||
if (mWriteFD) {
|
||||
#if defined(XP_WIN)
|
||||
AttachShutdownLayer(mWriteFD);
|
||||
#endif
|
||||
PR_Close(mWriteFD);
|
||||
}
|
||||
if (mReadFD) {
|
||||
#if defined(XP_WIN)
|
||||
AttachShutdownLayer(mReadFD);
|
||||
#endif
|
||||
PR_Close(mReadFD);
|
||||
}
|
||||
}
|
||||
|
||||
// we do not record signals on the socket thread
|
||||
// because the socket thread can reliably look at its
|
||||
// own runnable queue before selecting a poll time
|
||||
// this is the "service the network without blocking" comment in
|
||||
// nsSocketTransportService2.cpp
|
||||
bool
|
||||
PollableEvent::Signal()
|
||||
{
|
||||
SOCKET_LOG(("PollableEvent::Signal\n"));
|
||||
|
||||
if (!mWriteFD) {
|
||||
SOCKET_LOG(("PollableEvent::Signal Failed on no FD\n"));
|
||||
return false;
|
||||
}
|
||||
if (PR_GetCurrentThread() == gSocketThread) {
|
||||
SOCKET_LOG(("PollableEvent::Signal OnSocketThread nop\n"));
|
||||
return true;
|
||||
}
|
||||
if (mSignaled) {
|
||||
return true;
|
||||
}
|
||||
mSignaled = true;
|
||||
int32_t status = PR_Write(mWriteFD, "M", 1);
|
||||
SOCKET_LOG(("PollableEvent::Signal PR_Write %d\n", status));
|
||||
if (status != 1) {
|
||||
NS_WARNING("PollableEvent::Signal Failed\n");
|
||||
SOCKET_LOG(("PollableEvent::Signal Failed\n"));
|
||||
}
|
||||
return (status == 1);
|
||||
}
|
||||
|
||||
bool
|
||||
PollableEvent::Clear()
|
||||
{
|
||||
// necessary because of the "dont signal on socket thread" optimization
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
SOCKET_LOG(("PollableEvent::Clear\n"));
|
||||
mSignaled = false;
|
||||
if (!mReadFD) {
|
||||
SOCKET_LOG(("PollableEvent::Clear mReadFD is null\n"));
|
||||
return false;
|
||||
}
|
||||
char buf[2048];
|
||||
int32_t status = PR_Read(mReadFD, buf, 2048);
|
||||
SOCKET_LOG(("PollableEvent::Signal PR_Read %d\n", status));
|
||||
|
||||
if (status == 1) {
|
||||
return true;
|
||||
}
|
||||
if (status == 0) {
|
||||
SOCKET_LOG(("PollableEvent::Clear EOF!\n"));
|
||||
return false;
|
||||
}
|
||||
if (status > 1) {
|
||||
MOZ_ASSERT(false);
|
||||
SOCKET_LOG(("PollableEvent::Clear Unexpected events\n"));
|
||||
Clear();
|
||||
return true;
|
||||
}
|
||||
PRErrorCode code = PR_GetError();
|
||||
if (code == PR_WOULD_BLOCK_ERROR) {
|
||||
return true;
|
||||
}
|
||||
SOCKET_LOG(("PollableEvent::Clear unexpected error %d\n", code));
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
@ -1,38 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef PollableEvent_h__
|
||||
#define PollableEvent_h__
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// class must be called locked
|
||||
class PollableEvent
|
||||
{
|
||||
public:
|
||||
PollableEvent();
|
||||
~PollableEvent();
|
||||
|
||||
// Signal/Clear return false only if they fail
|
||||
bool Signal();
|
||||
bool Clear();
|
||||
bool Valid() { return mWriteFD && mReadFD; }
|
||||
|
||||
PRFileDesc *PollableFD() { return mReadFD; }
|
||||
|
||||
private:
|
||||
PRFileDesc *mWriteFD;
|
||||
PRFileDesc *mReadFD;
|
||||
bool mSignaled;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -249,7 +249,6 @@ UNIFIED_SOURCES += [
|
||||
'nsURLHelper.cpp',
|
||||
'nsURLParsers.cpp',
|
||||
'OfflineObserver.cpp',
|
||||
'PollableEvent.cpp',
|
||||
'Predictor.cpp',
|
||||
'ProxyAutoConfig.cpp',
|
||||
'RedirectChannelRegistrar.cpp',
|
||||
|
@ -87,13 +87,13 @@ DebugMutexAutoLock::~DebugMutexAutoLock()
|
||||
|
||||
nsSocketTransportService::nsSocketTransportService()
|
||||
: mThread(nullptr)
|
||||
, mThreadEvent(nullptr)
|
||||
, mAutodialEnabled(false)
|
||||
, mLock("nsSocketTransportService::mLock")
|
||||
, mInitialized(false)
|
||||
, mShuttingDown(false)
|
||||
, mOffline(false)
|
||||
, mGoingOffline(false)
|
||||
, mRawThread(nullptr)
|
||||
, mActiveListSize(SOCKET_LIMIT_MIN)
|
||||
, mIdleListSize(SOCKET_LIMIT_MIN)
|
||||
, mActiveCount(0)
|
||||
@ -131,6 +131,9 @@ nsSocketTransportService::~nsSocketTransportService()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
|
||||
NS_ASSERTION(!mInitialized, "not shutdown properly");
|
||||
|
||||
if (mThreadEvent)
|
||||
PR_DestroyPollableEvent(mThreadEvent);
|
||||
|
||||
free(mActiveList);
|
||||
free(mIdleList);
|
||||
@ -432,7 +435,7 @@ nsSocketTransportService::PollTimeout()
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsSocketTransportService::Poll(uint32_t *interval,
|
||||
nsSocketTransportService::Poll(bool wait, uint32_t *interval,
|
||||
TimeDuration *pollDuration)
|
||||
{
|
||||
PRPollDesc *pollList;
|
||||
@ -440,16 +443,11 @@ nsSocketTransportService::Poll(uint32_t *interval,
|
||||
PRIntervalTime pollTimeout;
|
||||
*pollDuration = 0;
|
||||
|
||||
// If there are pending events for this thread then
|
||||
// DoPollIteration() should service the network without blocking.
|
||||
bool pendingEvents = false;
|
||||
mRawThread->HasPendingEvents(&pendingEvents);
|
||||
|
||||
if (mPollList[0].fd) {
|
||||
mPollList[0].out_flags = 0;
|
||||
pollList = mPollList;
|
||||
pollCount = mActiveCount + 1;
|
||||
pollTimeout = pendingEvents ? PR_INTERVAL_NO_WAIT : PollTimeout();
|
||||
pollTimeout = PollTimeout();
|
||||
}
|
||||
else {
|
||||
// no pollable event, so busy wait...
|
||||
@ -458,10 +456,12 @@ nsSocketTransportService::Poll(uint32_t *interval,
|
||||
pollList = &mPollList[1];
|
||||
else
|
||||
pollList = nullptr;
|
||||
pollTimeout =
|
||||
pendingEvents ? PR_INTERVAL_NO_WAIT : PR_MillisecondsToInterval(25);
|
||||
pollTimeout = PR_MillisecondsToInterval(25);
|
||||
}
|
||||
|
||||
if (!wait)
|
||||
pollTimeout = PR_INTERVAL_NO_WAIT;
|
||||
|
||||
PRIntervalTime ts = PR_IntervalNow();
|
||||
|
||||
TimeStamp pollStart;
|
||||
@ -513,6 +513,24 @@ nsSocketTransportService::Init()
|
||||
if (mShuttingDown)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (!mThreadEvent) {
|
||||
mThreadEvent = PR_NewPollableEvent();
|
||||
//
|
||||
// NOTE: per bug 190000, this failure could be caused by Zone-Alarm
|
||||
// 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 :-(
|
||||
//
|
||||
if (!mThreadEvent) {
|
||||
NS_WARNING("running socket transport thread without a pollable event");
|
||||
SOCKET_LOG(("running socket transport thread without a pollable event"));
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(thread), this);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -566,9 +584,9 @@ nsSocketTransportService::Shutdown()
|
||||
// signal the socket thread to shutdown
|
||||
mShuttingDown = true;
|
||||
|
||||
if (mPollableEvent) {
|
||||
mPollableEvent->Signal();
|
||||
}
|
||||
if (mThreadEvent)
|
||||
PR_SetPollableEvent(mThreadEvent);
|
||||
// else wait for Poll timeout
|
||||
}
|
||||
|
||||
// join with thread
|
||||
@ -617,9 +635,8 @@ nsSocketTransportService::SetOffline(bool offline)
|
||||
else if (mOffline && !offline) {
|
||||
mOffline = false;
|
||||
}
|
||||
if (mPollableEvent) {
|
||||
mPollableEvent->Signal();
|
||||
}
|
||||
if (mThreadEvent)
|
||||
PR_SetPollableEvent(mThreadEvent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -732,19 +749,9 @@ nsSocketTransportService::SetAutodialEnabled(bool value)
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransportService::OnDispatchedEvent(nsIThreadInternal *thread)
|
||||
{
|
||||
if (PR_GetCurrentThread() == gSocketThread) {
|
||||
// this check is redundant to one done inside ::Signal(), but
|
||||
// we can do it here and skip obtaining the lock - given that
|
||||
// this is a relatively common occurance its worth the
|
||||
// redundant code
|
||||
SOCKET_LOG(("OnDispatchedEvent Same Thread Skip Signal\n"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DebugMutexAutoLock lock(mLock);
|
||||
if (mPollableEvent) {
|
||||
mPollableEvent->Signal();
|
||||
}
|
||||
if (mThreadEvent)
|
||||
PR_SetPollableEvent(mThreadEvent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -789,34 +796,15 @@ nsSocketTransportService::Run()
|
||||
|
||||
gSocketThread = PR_GetCurrentThread();
|
||||
|
||||
{
|
||||
DebugMutexAutoLock lock(mLock);
|
||||
mPollableEvent.reset(new PollableEvent());
|
||||
//
|
||||
// NOTE: per bug 190000, this failure could be caused by Zone-Alarm
|
||||
// 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 (it 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 :-(
|
||||
//
|
||||
if (!mPollableEvent->Valid()) {
|
||||
mPollableEvent = nullptr;
|
||||
NS_WARNING("running socket transport thread without a pollable event");
|
||||
SOCKET_LOG(("running socket transport thread without a pollable event"));
|
||||
}
|
||||
// add thread event to poll list (mThreadEvent may be nullptr)
|
||||
mPollList[0].fd = mThreadEvent;
|
||||
mPollList[0].in_flags = PR_POLL_READ;
|
||||
mPollList[0].out_flags = 0;
|
||||
|
||||
mPollList[0].fd = mPollableEvent ? mPollableEvent->PollableFD() : nullptr;
|
||||
mPollList[0].in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
|
||||
mPollList[0].out_flags = 0;
|
||||
}
|
||||
|
||||
mRawThread = NS_GetCurrentThread();
|
||||
nsIThread *thread = NS_GetCurrentThread();
|
||||
|
||||
// hook ourselves up to observe event processing for this thread
|
||||
nsCOMPtr<nsIThreadInternal> threadInt = do_QueryInterface(mRawThread);
|
||||
nsCOMPtr<nsIThreadInternal> threadInt = do_QueryInterface(thread);
|
||||
threadInt->SetObserver(this);
|
||||
|
||||
// make sure the pseudo random number generator is seeded on this thread
|
||||
@ -845,6 +833,7 @@ nsSocketTransportService::Run()
|
||||
|
||||
for (;;) {
|
||||
bool pendingEvents = false;
|
||||
thread->HasPendingEvents(&pendingEvents);
|
||||
|
||||
numberOfPendingEvents = 0;
|
||||
numberOfPendingEventsLastCycle = 0;
|
||||
@ -859,7 +848,9 @@ nsSocketTransportService::Run()
|
||||
pollCycleStart = TimeStamp::NowLoRes();
|
||||
}
|
||||
|
||||
DoPollIteration(&singlePollDuration);
|
||||
// If there are pending events for this thread then
|
||||
// DoPollIteration() should service the network without blocking.
|
||||
DoPollIteration(!pendingEvents, &singlePollDuration);
|
||||
|
||||
if (mTelemetryEnabledPref && !pollCycleStart.IsNull()) {
|
||||
Telemetry::Accumulate(Telemetry::STS_POLL_BLOCK_TIME,
|
||||
@ -871,7 +862,11 @@ nsSocketTransportService::Run()
|
||||
pollDuration += singlePollDuration;
|
||||
}
|
||||
|
||||
mRawThread->HasPendingEvents(&pendingEvents);
|
||||
// If nothing was pending before the poll, it might be now
|
||||
if (!pendingEvents) {
|
||||
thread->HasPendingEvents(&pendingEvents);
|
||||
}
|
||||
|
||||
if (pendingEvents) {
|
||||
if (!mServingPendingQueue) {
|
||||
nsresult rv = Dispatch(NS_NewRunnableMethod(this,
|
||||
@ -895,10 +890,10 @@ nsSocketTransportService::Run()
|
||||
}
|
||||
TimeStamp eventQueueStart = TimeStamp::NowLoRes();
|
||||
do {
|
||||
NS_ProcessNextEvent(mRawThread);
|
||||
NS_ProcessNextEvent(thread);
|
||||
numberOfPendingEvents++;
|
||||
pendingEvents = false;
|
||||
mRawThread->HasPendingEvents(&pendingEvents);
|
||||
thread->HasPendingEvents(&pendingEvents);
|
||||
} while (pendingEvents && mServingPendingQueue &&
|
||||
((TimeStamp::NowLoRes() -
|
||||
eventQueueStart).ToMilliseconds() <
|
||||
@ -956,7 +951,7 @@ nsSocketTransportService::Run()
|
||||
|
||||
// Final pass over the event queue. This makes sure that events posted by
|
||||
// socket detach handlers get processed.
|
||||
NS_ProcessPendingEvents(mRawThread);
|
||||
NS_ProcessPendingEvents(thread);
|
||||
|
||||
gSocketThread = nullptr;
|
||||
|
||||
@ -995,11 +990,12 @@ nsSocketTransportService::Reset(bool aGuardLocals)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSocketTransportService::DoPollIteration(TimeDuration *pollDuration)
|
||||
nsSocketTransportService::DoPollIteration(bool wait, TimeDuration *pollDuration)
|
||||
{
|
||||
SOCKET_LOG(("STS poll iter\n"));
|
||||
SOCKET_LOG(("STS poll iter [%d]\n", wait));
|
||||
|
||||
int32_t i, count;
|
||||
|
||||
//
|
||||
// poll loop
|
||||
//
|
||||
@ -1058,7 +1054,7 @@ nsSocketTransportService::DoPollIteration(TimeDuration *pollDuration)
|
||||
*pollDuration = 0;
|
||||
if (!gIOService->IsNetTearingDown()) {
|
||||
// Let's not do polling during shutdown.
|
||||
n = Poll(&pollInterval, pollDuration);
|
||||
n = Poll(wait, &pollInterval, pollDuration);
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
@ -1114,28 +1110,29 @@ nsSocketTransportService::DoPollIteration(TimeDuration *pollDuration)
|
||||
DetachSocket(mActiveList, &mActiveList[i]);
|
||||
}
|
||||
|
||||
if (n != 0 && (mPollList[0].out_flags & (PR_POLL_READ | PR_POLL_EXCEPT))) {
|
||||
DebugMutexAutoLock lock(mLock);
|
||||
|
||||
// acknowledge pollable event (should not block)
|
||||
if (mPollableEvent &&
|
||||
((mPollList[0].out_flags & PR_POLL_EXCEPT) ||
|
||||
!mPollableEvent->Clear())) {
|
||||
if (n != 0 && mPollList[0].out_flags == PR_POLL_READ) {
|
||||
// acknowledge pollable event (wait should not block)
|
||||
if (PR_WaitForPollableEvent(mThreadEvent) != PR_SUCCESS) {
|
||||
// On Windows, the TCP loopback connection in the
|
||||
// pollable event may become broken when a laptop
|
||||
// switches between wired and wireless networks or
|
||||
// wakes up from hibernation. We try to create a
|
||||
// new pollable event. If that fails, we fall back
|
||||
// on "busy wait".
|
||||
NS_WARNING("Trying to repair mPollableEvent");
|
||||
mPollableEvent.reset(new PollableEvent());
|
||||
if (!mPollableEvent->Valid()) {
|
||||
mPollableEvent = nullptr;
|
||||
{
|
||||
DebugMutexAutoLock lock(mLock);
|
||||
PR_DestroyPollableEvent(mThreadEvent);
|
||||
mThreadEvent = PR_NewPollableEvent();
|
||||
}
|
||||
SOCKET_LOG(("running socket transport thread without "
|
||||
"a pollable event now valid=%d", mPollableEvent->Valid()));
|
||||
mPollList[0].fd = mPollableEvent ? mPollableEvent->PollableFD() : nullptr;
|
||||
mPollList[0].in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
|
||||
if (!mThreadEvent) {
|
||||
NS_WARNING("running socket transport thread without "
|
||||
"a pollable event");
|
||||
SOCKET_LOG(("running socket transport thread without "
|
||||
"a pollable event"));
|
||||
}
|
||||
mPollList[0].fd = mThreadEvent;
|
||||
// mPollList[0].in_flags was already set to PR_POLL_READ
|
||||
// in Run().
|
||||
mPollList[0].out_flags = 0;
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,6 @@
|
||||
#include "mozilla/net/DashboardTypes.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "PollableEvent.h"
|
||||
|
||||
class nsASocketHandler;
|
||||
struct PRPollDesc;
|
||||
@ -126,7 +124,14 @@ private:
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
nsCOMPtr<nsIThread> mThread; // protected by mLock
|
||||
mozilla::UniquePtr<mozilla::net::PollableEvent> mPollableEvent;
|
||||
PRFileDesc *mThreadEvent;
|
||||
// protected by mLock. mThreadEvent may change
|
||||
// if the old pollable event is broken. only
|
||||
// the socket thread may change mThreadEvent;
|
||||
// it needs to lock mLock only when it changes
|
||||
// mThreadEvent. other threads don't change
|
||||
// mThreadEvent; they need to lock mLock
|
||||
// whenever they access mThreadEvent.
|
||||
bool mAutodialEnabled;
|
||||
// pref to control autodial code
|
||||
|
||||
@ -168,7 +173,6 @@ private:
|
||||
|
||||
SocketContext *mActiveList; /* mListSize entries */
|
||||
SocketContext *mIdleList; /* mListSize entries */
|
||||
nsIThread *mRawThread;
|
||||
|
||||
uint32_t mActiveListSize;
|
||||
uint32_t mIdleListSize;
|
||||
@ -193,16 +197,18 @@ private:
|
||||
//-------------------------------------------------------------------------
|
||||
// poll list (socket thread only)
|
||||
//
|
||||
// first element of the poll list is mPollableEvent (or null if the pollable
|
||||
// first element of the poll list is mThreadEvent (or null if the pollable
|
||||
// event cannot be created).
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
PRPollDesc *mPollList; /* mListSize + 1 entries */
|
||||
|
||||
PRIntervalTime PollTimeout(); // computes ideal poll timeout
|
||||
nsresult DoPollIteration(mozilla::TimeDuration *pollDuration);
|
||||
nsresult DoPollIteration(bool wait,
|
||||
mozilla::TimeDuration *pollDuration);
|
||||
// perfoms a single poll iteration
|
||||
int32_t Poll(uint32_t *interval,
|
||||
int32_t Poll(bool wait,
|
||||
uint32_t *interval,
|
||||
mozilla::TimeDuration *pollDuration);
|
||||
// calls PR_Poll. the out param
|
||||
// interval indicates the poll
|
||||
|
@ -12,7 +12,6 @@ src_list = [
|
||||
]
|
||||
|
||||
netwerk_base_src = [
|
||||
'PollableEvent.cpp',
|
||||
'nsDNSPrefetch.cpp',
|
||||
'nsNetAddr.cpp',
|
||||
'nsSocketTransportService2.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user