Bug 614286 - Don't initialize the socket transport service unless we know that we're online; r=bzbarsky a=blocking-beta8+

This commit is contained in:
Ehsan Akhgari 2010-11-25 00:20:11 -05:00
parent e6fd2c9dad
commit dfed869c9f
8 changed files with 116 additions and 41 deletions

View File

@ -174,7 +174,7 @@ PRUint32 nsIOService::gDefaultSegmentCount = 24;
////////////////////////////////////////////////////////////////////////////////
nsIOService::nsIOService()
: mOffline(PR_FALSE)
: mOffline(PR_TRUE)
, mOfflineForProfileChange(PR_FALSE)
, mManageOfflineStatus(PR_TRUE)
, mSettingOffline(PR_FALSE)
@ -191,21 +191,11 @@ nsIOService::Init()
NS_TIME_FUNCTION;
nsresult rv;
// We need to get references to these services so that we can shut them
// We need to get references to the DNS service so that we can shut it
// down later. If we wait until the nsIOService is being shut down,
// GetService will fail at that point.
// TODO(darin): Load the Socket and DNS services lazily.
mSocketTransportService = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
NS_WARNING("failed to get socket transport service");
return rv;
}
NS_TIME_FUNCTION_MARK("got SocketTransportService");
mDNSService = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
NS_WARNING("failed to get DNS service");
@ -293,7 +283,29 @@ nsIOService::Init()
nsIOService::~nsIOService()
{
gIOService = nsnull;
}
}
nsresult
nsIOService::InitializeSocketTransportService()
{
NS_TIME_FUNCTION;
nsresult rv = NS_OK;
if (!mSocketTransportService) {
mSocketTransportService = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
NS_WARNING("failed to get socket transport service");
}
}
if (mSocketTransportService) {
rv = mSocketTransportService->Init();
NS_ASSERTION(NS_SUCCEEDED(rv), "socket transport service init failed");
}
return rv;
}
nsIOService*
nsIOService::GetInstance() {
@ -742,10 +754,7 @@ nsIOService::SetOffline(PRBool offline)
rv = mDNSService->Init();
NS_ASSERTION(NS_SUCCEEDED(rv), "DNS service init failed");
}
if (mSocketTransportService) {
rv = mSocketTransportService->Init();
NS_ASSERTION(NS_SUCCEEDED(rv), "socket transport service init failed");
}
InitializeSocketTransportService();
mOffline = PR_FALSE; // indicate success only AFTER we've
// brought up the services

View File

@ -108,6 +108,10 @@ public:
PRBool IsOffline() { return mOffline; }
PRBool IsLinkUp();
PRBool IsComingOnline() const {
return mOffline && mSettingOffline && !mSetOfflineValue;
}
private:
// These shouldn't be called directly:
// - construct using GetInstance
@ -129,6 +133,8 @@ private:
NS_HIDDEN_(void) GetPrefBranch(nsIPrefBranch2 **);
NS_HIDDEN_(void) ParsePortList(nsIPrefBranch *prefBranch, const char *pref, PRBool remove);
nsresult InitializeSocketTransportService();
private:
PRPackedBool mOffline;
PRPackedBool mOfflineForProfileChange;

View File

@ -52,6 +52,7 @@
#include "nsIPrefService.h"
#include "nsIPrefBranch2.h"
#include "nsServiceManagerUtils.h"
#include "nsIOService.h"
#include "mozilla/FunctionTimer.h"
@ -395,6 +396,10 @@ nsSocketTransportService::Init()
if (mShuttingDown)
return NS_ERROR_UNEXPECTED;
// Don't initialize inside the offline mode
if (gIOService->IsOffline() && !gIOService->IsComingOnline())
return NS_ERROR_OFFLINE;
if (!mThreadEvent) {
mThreadEvent = PR_NewPollableEvent();
//

View File

@ -57,6 +57,7 @@
#include "prmon.h"
#include "prio.h"
#include "plstr.h"
#include "nsIOService.h"
#include "mozilla/FunctionTimer.h"
@ -382,6 +383,13 @@ nsDNSService::Init()
if (enableIDN)
idn = do_GetService(NS_IDNSERVICE_CONTRACTID);
nsDNSPrefetch::Initialize(this);
// Don't initialize the resolver if we're in offline mode.
// Later on, the IO service will reinitialize us when going online.
if (gIOService->IsOffline() && !gIOService->IsComingOnline())
return NS_OK;
nsRefPtr<nsHostResolver> res;
nsresult rv = nsHostResolver::Create(maxCacheEntries,
maxCacheLifetime,
@ -397,8 +405,6 @@ nsDNSService::Init()
// Disable prefetching either by explicit preference or if a manual proxy is configured
mDisablePrefetch = disablePrefetch || (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL);
}
nsDNSPrefetch::Initialize(this);
return rv;
}
@ -571,8 +577,8 @@ nsDNSService::Observe(nsISupports *subject, const char *topic, const PRUnichar *
if (mResolver) {
Shutdown();
Init();
}
Init();
return NS_OK;
}

View File

@ -43,6 +43,7 @@
#include "nsAutoLock.h"
#include "nsNetCID.h"
#include "nsCOMPtr.h"
#include "nsNetUtil.h"
#include "nsIServiceManager.h"
@ -100,6 +101,32 @@ nsHttpConnectionMgr::~nsHttpConnectionMgr()
nsAutoMonitor::DestroyMonitor(mMonitor);
}
nsresult
nsHttpConnectionMgr::EnsureSocketThreadTargetIfOnline()
{
nsresult rv;
nsCOMPtr<nsIEventTarget> sts;
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
if (NS_SUCCEEDED(rv)) {
PRBool offline = PR_TRUE;
ioService->GetOffline(&offline);
if (!offline) {
sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
}
}
nsAutoMonitor mon(mMonitor);
// do nothing if already initialized
if (mSocketThreadTarget)
return NS_OK;
mSocketThreadTarget = sts;
return rv;
}
nsresult
nsHttpConnectionMgr::Init(PRUint16 maxConns,
PRUint16 maxConnsPerHost,
@ -111,28 +138,19 @@ nsHttpConnectionMgr::Init(PRUint16 maxConns,
{
LOG(("nsHttpConnectionMgr::Init\n"));
nsresult rv;
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
{
nsAutoMonitor mon(mMonitor);
nsAutoMonitor mon(mMonitor);
mMaxConns = maxConns;
mMaxConnsPerHost = maxConnsPerHost;
mMaxConnsPerProxy = maxConnsPerProxy;
mMaxPersistConnsPerHost = maxPersistConnsPerHost;
mMaxPersistConnsPerProxy = maxPersistConnsPerProxy;
mMaxRequestDelay = maxRequestDelay;
mMaxPipelinedRequests = maxPipelinedRequests;
}
// do nothing if already initialized
if (mSocketThreadTarget)
return NS_OK;
// no need to do any special synchronization here since there cannot be
// any activity on the socket thread (because Shutdown is synchronous).
mMaxConns = maxConns;
mMaxConnsPerHost = maxConnsPerHost;
mMaxConnsPerProxy = maxConnsPerProxy;
mMaxPersistConnsPerHost = maxPersistConnsPerHost;
mMaxPersistConnsPerProxy = maxPersistConnsPerProxy;
mMaxRequestDelay = maxRequestDelay;
mMaxPipelinedRequests = maxPipelinedRequests;
mSocketThreadTarget = sts;
return rv;
return EnsureSocketThreadTargetIfOnline();
}
nsresult
@ -166,6 +184,12 @@ nsHttpConnectionMgr::Shutdown()
nsresult
nsHttpConnectionMgr::PostEvent(nsConnEventHandler handler, PRInt32 iparam, void *vparam)
{
// This object doesn't get reinitialized if the offline state changes, so our
// socket thread target might be uninitialized if we were offline when this
// object was being initialized, and we go online later on. This call takes
// care of initializing the socket thread target if that's the case.
EnsureSocketThreadTargetIfOnline();
nsAutoMonitor mon(mMonitor);
nsresult rv;
@ -285,6 +309,12 @@ nsHttpConnectionMgr::PruneDeadConnections()
nsresult
nsHttpConnectionMgr::GetSocketThreadTarget(nsIEventTarget **target)
{
// This object doesn't get reinitialized if the offline state changes, so our
// socket thread target might be uninitialized if we were offline when this
// object was being initialized, and we go online later on. This call takes
// care of initializing the socket thread target if that's the case.
EnsureSocketThreadTargetIfOnline();
nsAutoMonitor mon(mMonitor);
NS_IF_ADDREF(*target = mSocketThreadTarget);
return NS_OK;

View File

@ -215,6 +215,7 @@ private:
PRUint8 caps, nsHttpConnection *);
PRBool BuildPipeline(nsConnectionEntry *, nsAHttpTransaction *, nsHttpPipeline **);
nsresult ProcessNewTransaction(nsHttpTransaction *);
nsresult EnsureSocketThreadTargetIfOnline();
// message handlers have this signature
typedef void (nsHttpConnectionMgr:: *nsConnEventHandler)(PRInt32, void *);

View File

@ -0,0 +1,10 @@
function run_test() {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var linkService = Components.classes["@mozilla.org/network/network-link-service;1"]
.getService(Components.interfaces.nsINetworkLinkService);
// The offline status should depends on the link status
do_check_neq(ioService.offline, linkService.isLinkUp);
}

View File

@ -0,0 +1,8 @@
function run_test() {
try {
var sts = Components.classes["@mozilla.org/network/socket-transport-service;1"]
.getService(Components.interfaces.nsISocketTransportService);
} catch(e) {}
do_check_true(!!sts);
}