Bug 1240481 - Limit PR_Close calls during shutdown. r=mcmanus

This commit is contained in:
Dragana Damjanovic 2016-01-18 08:20:00 +01:00
parent 520e8f8f53
commit 94619712b9
6 changed files with 34 additions and 5 deletions

View File

@ -1481,6 +1481,10 @@ pref("network.ftp.control.qos", 0);
// The max time to spend on xpcom events between two polls in ms.
pref("network.sts.max_time_for_events_between_two_polls", 100);
// During shutdown we limit PR_Close calls. If time exceeds this pref (in ms)
// let sockets just leak.
pref("network.sts.max_time_for_pr_close_during_shutdown", 5000);
// </http>
// 2147483647 == PR_INT32_MAX == ~2 GB

View File

@ -190,6 +190,7 @@ nsIOService::nsIOService()
, mLastOfflineStateChange(PR_IntervalNow())
, mLastConnectivityChange(PR_IntervalNow())
, mLastNetworkLinkChange(PR_IntervalNow())
, mNetTearingDownStarted(0)
{
}
@ -1419,6 +1420,7 @@ nsIOService::Observe(nsISupports *subject,
} else if (!strcmp(topic, kProfileChangeNetTeardownTopic)) {
if (!mOffline) {
mOfflineForProfileChange = true;
mNetTearingDownStarted = PR_IntervalNow();
if (gHttpHandler) {
gHttpHandler->ShutdownConnectionManager();
}
@ -1447,7 +1449,9 @@ nsIOService::Observe(nsISupports *subject,
// changes of the offline status from now. We must not allow going
// online after this point.
mShutdown = true;
if (!mOfflineForProfileChange) {
mNetTearingDownStarted = PR_IntervalNow();
}
if (gHttpHandler) {
gHttpHandler->ShutdownConnectionManager();
}

View File

@ -85,6 +85,7 @@ public:
PRIntervalTime LastConnectivityChange() { return mLastConnectivityChange; }
PRIntervalTime LastNetworkLinkChange() { return mLastNetworkLinkChange; }
bool IsNetTearingDown() { return mShutdown || mOfflineForProfileChange; }
PRIntervalTime NetTearingDownStarted() { return mNetTearingDownStarted; }
bool IsLinkUp();
// Should only be called from NeckoChild. Use SetAppOffline instead.
@ -180,9 +181,12 @@ private:
// PR_ConnectContinue and PR_Close blocking time. If we spend very long
// time in any of these functions we want to know if and what network
// change has happened shortly before.
mozilla::Atomic<PRIntervalTime> mLastOfflineStateChange;
mozilla::Atomic<PRIntervalTime> mLastConnectivityChange;
mozilla::Atomic<PRIntervalTime> mLastNetworkLinkChange;
mozilla::Atomic<PRIntervalTime> mLastOfflineStateChange;
mozilla::Atomic<PRIntervalTime> mLastConnectivityChange;
mozilla::Atomic<PRIntervalTime> mLastNetworkLinkChange;
// Time a network tearing down started.
mozilla::Atomic<PRIntervalTime> mNetTearingDownStarted;
public:
// Used for all default buffer sizes that necko allocates.
static uint32_t gDefaultSegmentSize;

View File

@ -1748,7 +1748,12 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd)
SOCKET_LOG(("JIMB: ReleaseFD_Locked: mFDref = %d\n", mFDref));
if (--mFDref == 0) {
if (PR_GetCurrentThread() == gSocketThread) {
if (gIOService->IsNetTearingDown() &&
((PR_IntervalNow() - gIOService->NetTearingDownStarted()) >
gSocketTransportService->MaxTimeForPrClosePref())) {
// If shutdown last to long, let the socket leak and do not close it.
SOCKET_LOG(("Intentional leak"));
} else if (PR_GetCurrentThread() == gSocketThread) {
SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%p]\n", this));
PR_Close(mFD);
} else {

View File

@ -47,6 +47,7 @@ Atomic<PRThread*, Relaxed> gSocketThread;
#define BLIP_INTERVAL_PREF "network.activity.blipIntervalMilliseconds"
#define MAX_TIME_BETWEEN_TWO_POLLS "network.sts.max_time_for_events_between_two_polls"
#define TELEMETRY_PREF "toolkit.telemetry.enabled"
#define MAX_TIME_FOR_PR_CLOSE_DURING_SHUTDOWN "network.sts.max_time_for_pr_close_during_shutdown"
uint32_t nsSocketTransportService::gMaxCount;
PRCallOnceType nsSocketTransportService::gMaxCountInitOnce;
@ -111,6 +112,7 @@ nsSocketTransportService::nsSocketTransportService()
, mServingPendingQueue(false)
, mMaxTimePerPollIter(100)
, mTelemetryEnabledPref(false)
, mMaxTimeForPrClosePref(PR_SecondsToInterval(5))
, mProbedMaxCount(false)
{
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
@ -550,6 +552,7 @@ nsSocketTransportService::Init()
tmpPrefService->AddObserver(KEEPALIVE_PROBE_COUNT_PREF, this, false);
tmpPrefService->AddObserver(MAX_TIME_BETWEEN_TWO_POLLS, this, false);
tmpPrefService->AddObserver(TELEMETRY_PREF, this, false);
tmpPrefService->AddObserver(MAX_TIME_FOR_PR_CLOSE_DURING_SHUTDOWN, this, false);
}
UpdatePrefs();
@ -1218,6 +1221,13 @@ nsSocketTransportService::UpdatePrefs()
if (NS_SUCCEEDED(rv)) {
mTelemetryEnabledPref = telemetryPref;
}
int32_t maxTimeForPrClosePref;
rv = tmpPrefService->GetIntPref(MAX_TIME_FOR_PR_CLOSE_DURING_SHUTDOWN,
&maxTimeForPrClosePref);
if (NS_SUCCEEDED(rv) && maxTimeForPrClosePref >=0) {
mMaxTimeForPrClosePref = PR_MillisecondsToInterval(maxTimeForPrClosePref);
}
}
return NS_OK;

View File

@ -112,6 +112,7 @@ public:
bool IsKeepaliveEnabled() { return mKeepaliveEnabledPref; }
bool IsTelemetryEnabled() { return mTelemetryEnabledPref; }
PRIntervalTime MaxTimeForPrClosePref() {return mMaxTimeForPrClosePref; }
protected:
virtual ~nsSocketTransportService();
@ -237,6 +238,7 @@ private:
mozilla::Atomic<bool> mServingPendingQueue;
mozilla::Atomic<int32_t, mozilla::Relaxed> mMaxTimePerPollIter;
mozilla::Atomic<bool, mozilla::Relaxed> mTelemetryEnabledPref;
mozilla::Atomic<PRIntervalTime, mozilla::Relaxed> mMaxTimeForPrClosePref;
void OnKeepaliveEnabledPrefChange();
void NotifyKeepaliveEnabledPrefChange(SocketContext *sock);