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
Родитель 854aecd889
Коммит 06c9cbac52
6 изменённых файлов: 34 добавлений и 5 удалений

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

@ -1481,6 +1481,10 @@ pref("network.ftp.control.qos", 0);
// The max time to spend on xpcom events between two polls in ms. // The max time to spend on xpcom events between two polls in ms.
pref("network.sts.max_time_for_events_between_two_polls", 100); 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> // </http>
// 2147483647 == PR_INT32_MAX == ~2 GB // 2147483647 == PR_INT32_MAX == ~2 GB

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

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

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

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

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

@ -1748,7 +1748,12 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd)
SOCKET_LOG(("JIMB: ReleaseFD_Locked: mFDref = %d\n", mFDref)); SOCKET_LOG(("JIMB: ReleaseFD_Locked: mFDref = %d\n", mFDref));
if (--mFDref == 0) { 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)); SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%p]\n", this));
PR_Close(mFD); PR_Close(mFD);
} else { } else {

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

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

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

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