Backed out changeset d5d0b5994149 (bug 1152046) for b2g debug hustdown hangs

CLOSED TREE
This commit is contained in:
Nigel Babu 2015-09-16 11:44:12 +05:30
parent bc98239148
commit 2c66fb8d92
14 changed files with 439 additions and 240 deletions

View File

@ -0,0 +1,288 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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 "ClosingService.h"
#include "nsIOService.h"
class ClosingLayerSecret
{
public:
explicit ClosingLayerSecret(mozilla::net::ClosingService *aClosingService)
: mClosingService(aClosingService)
{
}
~ClosingLayerSecret()
{
mClosingService = nullptr;
}
nsRefPtr<mozilla::net::ClosingService> mClosingService;
};
namespace mozilla {
namespace net {
static PRIOMethods sTcpUdpPRCloseLayerMethods;
static PRIOMethods *sTcpUdpPRCloseLayerMethodsPtr = nullptr;
static PRDescIdentity sTcpUdpPRCloseLayerId;
static PRStatus
TcpUdpPRCloseLayerClose(PRFileDesc *aFd)
{
if (!aFd) {
return PR_FAILURE;
}
PRFileDesc* layer = PR_PopIOLayer(aFd, PR_TOP_IO_LAYER);
MOZ_RELEASE_ASSERT(layer &&
layer->identity == sTcpUdpPRCloseLayerId,
"Closing Layer not on top of stack");
ClosingLayerSecret *closingLayerSecret =
reinterpret_cast<ClosingLayerSecret *>(layer->secret);
PRStatus status = PR_SUCCESS;
if (aFd) {
// If this is called during shutdown do not call ..method->close(fd) and
// let it leak.
if (gIOService->IsShutdown()) {
// If the ClosingService layer is the first layer above PR_NSPR_IO_LAYER
// we are not going to leak anything, but the PR_Close will not be called.
PR_Free(aFd);
} else if (closingLayerSecret->mClosingService) {
closingLayerSecret->mClosingService->PostRequest(aFd);
} else {
// Socket is created before closing service has been started or there was
// a problem with starting it.
PR_Close(aFd);
}
}
layer->secret = nullptr;
layer->dtor(layer);
delete closingLayerSecret;
return status;
}
ClosingService* ClosingService::sInstance = nullptr;
ClosingService::ClosingService()
: mShutdown(false)
, mMonitor("ClosingService.mMonitor")
{
MOZ_ASSERT(!sInstance,
"multiple ClosingService instances!");
}
// static
void
ClosingService::Start()
{
if (!sTcpUdpPRCloseLayerMethodsPtr) {
sTcpUdpPRCloseLayerId = PR_GetUniqueIdentity("TCP and UDP PRClose layer");
PR_ASSERT(PR_INVALID_IO_LAYER != sTcpUdpPRCloseLayerId);
sTcpUdpPRCloseLayerMethods = *PR_GetDefaultIOMethods();
sTcpUdpPRCloseLayerMethods.close = TcpUdpPRCloseLayerClose;
sTcpUdpPRCloseLayerMethodsPtr = &sTcpUdpPRCloseLayerMethods;
}
if (!sInstance) {
ClosingService* service = new ClosingService();
if (NS_SUCCEEDED(service->StartInternal())) {
NS_ADDREF(service);
sInstance = service;
} else {
delete service;
}
}
}
nsresult
ClosingService::StartInternal()
{
mThread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_JOINABLE_THREAD, 4 * 4096);
if (!mThread) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
// static
nsresult
ClosingService::AttachIOLayer(PRFileDesc *aFd)
{
if (!sTcpUdpPRCloseLayerMethodsPtr) {
return NS_OK;
}
PRFileDesc * layer;
PRStatus status;
layer = PR_CreateIOLayerStub(sTcpUdpPRCloseLayerId,
sTcpUdpPRCloseLayerMethodsPtr);
if (!layer) {
return NS_OK;
}
ClosingLayerSecret *secret = new ClosingLayerSecret(sInstance);
layer->secret = reinterpret_cast<PRFilePrivate *>(secret);
status = PR_PushIOLayer(aFd, PR_NSPR_IO_LAYER, layer);
if (status == PR_FAILURE) {
delete secret;
PR_DELETE(layer);
}
return NS_OK;
}
void
ClosingService::PostRequest(PRFileDesc *aFd)
{
mozilla::MonitorAutoLock mon(mMonitor);
// Check if shutdown is called.
if (mShutdown) {
// Let the socket leak. We are in shutdown and some PRClose can take a long
// time. To prevent shutdown crash (bug 1152046) do not accept sockets any
// more.
// If the ClosingService layer is the first layer above PR_NSPR_IO_LAYER
// we are not going to leak anything, but PR_Close will not be called.
PR_Free(aFd);
return;
}
mQueue.AppendElement(aFd);
if (mQueue.Length() == 1) {
mon.Notify();
}
}
// static
void
ClosingService::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread());
if (sInstance) {
sInstance->ShutdownInternal();
NS_RELEASE(sInstance);
}
}
void
ClosingService::ShutdownInternal()
{
{
mozilla::MonitorAutoLock mon(mMonitor);
mShutdown = true;
// If it is waiting on the empty queue, wake it up.
if (mQueue.Length() == 0) {
mon.Notify();
}
}
if (mThread) {
PR_JoinThread(mThread);
mThread = nullptr;
}
}
void
ClosingService::ThreadFunc()
{
for (;;) {
PRFileDesc *fd;
{
mozilla::MonitorAutoLock mon(mMonitor);
while (!mShutdown && (mQueue.Length() == 0)) {
mon.Wait();
}
if (mShutdown) {
// If we are in shutdown leak the rest of the sockets.
for (uint32_t i = 0; i < mQueue.Length(); i++) {
fd = mQueue[i];
// If the ClosingService layer is the first layer above
// PR_NSPR_IO_LAYER we are not going to leak anything, but PR_Close
// will not be called.
PR_Free(fd);
}
mQueue.Clear();
return;
}
fd = mQueue[0];
mQueue.RemoveElementAt(0);
}
// Leave lock before closing socket. It can block for a long time and in
// case we accidentally attach this layer twice this would cause deadlock.
bool tcp = (PR_GetDescType(PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER)) ==
PR_DESC_SOCKET_TCP);
PRIntervalTime closeStarted = PR_IntervalNow();
fd->methods->close(fd);
// Post telemetry.
if (tcp) {
SendPRCloseTelemetry(closeStarted,
Telemetry::PRCLOSE_TCP_BLOCKING_TIME_NORMAL,
Telemetry::PRCLOSE_TCP_BLOCKING_TIME_SHUTDOWN,
Telemetry::PRCLOSE_TCP_BLOCKING_TIME_CONNECTIVITY_CHANGE,
Telemetry::PRCLOSE_TCP_BLOCKING_TIME_LINK_CHANGE,
Telemetry::PRCLOSE_TCP_BLOCKING_TIME_OFFLINE);
} else {
SendPRCloseTelemetry(closeStarted,
Telemetry::PRCLOSE_UDP_BLOCKING_TIME_NORMAL,
Telemetry::PRCLOSE_UDP_BLOCKING_TIME_SHUTDOWN,
Telemetry::PRCLOSE_UDP_BLOCKING_TIME_CONNECTIVITY_CHANGE,
Telemetry::PRCLOSE_UDP_BLOCKING_TIME_LINK_CHANGE,
Telemetry::PRCLOSE_UDP_BLOCKING_TIME_OFFLINE);
}
}
}
void
ClosingService::SendPRCloseTelemetry(PRIntervalTime aStart,
mozilla::Telemetry::ID aIDNormal,
mozilla::Telemetry::ID aIDShutdown,
mozilla::Telemetry::ID aIDConnectivityChange,
mozilla::Telemetry::ID aIDLinkChange,
mozilla::Telemetry::ID aIDOffline)
{
PRIntervalTime now = PR_IntervalNow();
if (gIOService->IsShutdown()) {
Telemetry::Accumulate(aIDShutdown,
PR_IntervalToMilliseconds(now - aStart));
} else if (PR_IntervalToSeconds(now - gIOService->LastConnectivityChange())
< 60) {
Telemetry::Accumulate(aIDConnectivityChange,
PR_IntervalToMilliseconds(now - aStart));
} else if (PR_IntervalToSeconds(now - gIOService->LastNetworkLinkChange())
< 60) {
Telemetry::Accumulate(aIDLinkChange,
PR_IntervalToMilliseconds(now - aStart));
} else if (PR_IntervalToSeconds(now - gIOService->LastOfflineStateChange())
< 60) {
Telemetry::Accumulate(aIDOffline,
PR_IntervalToMilliseconds(now - aStart));
} else {
Telemetry::Accumulate(aIDNormal,
PR_IntervalToMilliseconds(now - aStart));
}
}
} //namwspacw mozilla
} //namespace net

View File

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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 ClosingService_h__
#define ClosingService_h__
#include "nsTArray.h"
#include "nspr.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Monitor.h"
//-----------------------------------------------------------------------------
// ClosingService
//-----------------------------------------------------------------------------
// A helper class carrying call to PR_Close on FD to a separate thread -
// closingThread. This may be a workaround for shutdown blocks that are caused
// by serial calls to close on UDP and TCP sockets.
// This service is started by nsIOService and also the class adds itself as an
// observer to "xpcom-shutdown-threads" notification where we join the thread
// and remove reference.
// During worktime of the thread the class is also self-referenced,
// since observer service might throw the reference away sooner than the thread
// is actually done.
namespace mozilla {
namespace net {
class ClosingService final
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ClosingService)
ClosingService();
// Attaching this layer on tcp or udp sockets PRClose will be send to the
// closingThread.
static nsresult AttachIOLayer(PRFileDesc *aFd);
static void Start();
static void Shutdown();
void PostRequest(PRFileDesc *aFd);
private:
~ClosingService() {}
nsresult StartInternal();
void ShutdownInternal();
void ThreadFunc();
static void ThreadFunc(void *aClosure)
{ static_cast<ClosingService*>(aClosure)->ThreadFunc(); }
void SendPRCloseTelemetry(PRIntervalTime aStart,
mozilla::Telemetry::ID aIDNormal,
mozilla::Telemetry::ID aIDShutdown,
mozilla::Telemetry::ID aIDConnectivityChange,
mozilla::Telemetry::ID aIDLinkChange,
mozilla::Telemetry::ID aIDOffline);
static ClosingService* sInstance;
Atomic<bool> mShutdown;
nsTArray<PRFileDesc *> mQueue;
mozilla::Monitor mMonitor;
PRThread *mThread;
};
} // namespace net
} // namespace mozilla
#endif // ClosingService_h_

View File

@ -189,6 +189,7 @@ UNIFIED_SOURCES += [
'CaptivePortalService.cpp',
'ChannelDiverterChild.cpp',
'ChannelDiverterParent.cpp',
'ClosingService.cpp',
'Dashboard.cpp',
'EventTokenBucket.cpp',
'LoadContextInfo.cpp',

View File

@ -7,6 +7,7 @@
#include "mozilla/DebugOnly.h"
#include "nsIOService.h"
#include "nsIDOMNode.h"
#include "nsIProtocolHandler.h"
#include "nsIFileProtocolHandler.h"
#include "nscore.h"
@ -20,6 +21,7 @@
#include "nsIProxiedProtocolHandler.h"
#include "nsIProxyInfo.h"
#include "nsEscape.h"
#include "nsNetUtil.h"
#include "nsNetCID.h"
#include "nsCRT.h"
#include "nsSecCheckWrapChannel.h"
@ -42,6 +44,7 @@
#include "nsThreadUtils.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "mozilla/net/DNS.h"
#include "CaptivePortalService.h"

View File

@ -16,6 +16,7 @@
#include "nsProxyInfo.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "ClosingService.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "plstr.h"
@ -1194,7 +1195,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
if (NS_FAILED(rv)) {
SOCKET_LOG((" error pushing io layer [%u:%s rv=%x]\n", i, mTypes[i], rv));
if (fd) {
CloseSocket(fd, mSocketTransportService->IsTelemetryEnabled());
PR_Close(fd);
}
}
}
@ -1322,6 +1323,9 @@ nsSocketTransport::InitiateSocket()
// Attach network activity monitor
mozilla::net::NetworkActivityMonitor::AttachIOLayer(fd);
// Attach closing service.
ClosingService::AttachIOLayer(fd);
PRStatus status;
// Make the socket non-blocking...
@ -1358,7 +1362,7 @@ nsSocketTransport::InitiateSocket()
// inform socket transport about this newly created socket...
rv = mSocketTransportService->AttachSocket(fd, this);
if (NS_FAILED(rv)) {
CloseSocket(fd, mSocketTransportService->IsTelemetryEnabled());
PR_Close(fd);
return rv;
}
mAttached = true;
@ -1698,8 +1702,7 @@ public:
NS_IMETHOD Run()
{
nsSocketTransport::CloseSocket(mFD,
gSocketTransportService->IsTelemetryEnabled());
PR_Close(mFD);
return NS_OK;
}
private:
@ -1731,7 +1734,7 @@ nsSocketTransport::ReleaseFD_Locked(PRFileDesc *fd)
if (--mFDref == 0) {
if (PR_GetCurrentThread() == gSocketThread) {
SOCKET_LOG(("nsSocketTransport: calling PR_Close [this=%p]\n", this));
CloseSocket(mFD, mSocketTransportService->IsTelemetryEnabled());
PR_Close(mFD);
} else {
// Can't PR_Close() a socket off STS thread. Thunk it to STS to die
STS_PRCloseOnSocketTransport(mFD);
@ -3039,29 +3042,6 @@ nsSocketTransport::PRFileDescAutoLock::SetKeepaliveVals(bool aEnabled,
#endif
}
void
nsSocketTransport::CloseSocket(PRFileDesc *aFd, bool aTelemetryEnabled) {
// We use PRIntervalTime here because we need
// nsIOService::LastOfflineStateChange time and
// nsIOService::LastConectivityChange time to be atomic.
PRIntervalTime closeStarted;
if (aTelemetryEnabled) {
closeStarted = PR_IntervalNow();
}
PR_Close(aFd);
if (aTelemetryEnabled) {
SendPRBlockingTelemetry(closeStarted,
Telemetry::PRCLOSE_BLOCKING_TIME_NORMAL,
Telemetry::PRCLOSE_BLOCKING_TIME_SHUTDOWN,
Telemetry::PRCLOSE_BLOCKING_TIME_CONNECTIVITY_CHANGE,
Telemetry::PRCLOSE_BLOCKING_TIME_LINK_CHANGE,
Telemetry::PRCLOSE_BLOCKING_TIME_OFFLINE);
}
}
void
nsSocketTransport::SendPRBlockingTelemetry(PRIntervalTime aStart,
Telemetry::ID aIDNormal,

View File

@ -8,6 +8,7 @@
#include "nsSocketTransport2.h"
#include "NetworkActivityMonitor.h"
#include "mozilla/Preferences.h"
#include "ClosingService.h"
#endif // !defined(MOZILLA_XPCOMRT_API)
#include "nsASocketHandler.h"
#include "nsError.h"
@ -551,6 +552,13 @@ nsSocketTransportService::Init()
obsSvc->AddObserver(this, "last-pb-context-exited", false);
}
#if !defined(MOZILLA_XPCOMRT_API)
// Start the closing service. Actual PR_Close() will be carried out on
// a separate "closing" thread. Start the closing servicee here since this
// point is executed only once per session.
ClosingService::Start();
#endif //!defined(MOZILLA_XPCOMRT_API)
mInitialized = true;
return NS_OK;
}
@ -601,6 +609,7 @@ nsSocketTransportService::Shutdown()
#if !defined(MOZILLA_XPCOMRT_API)
mozilla::net::NetworkActivityMonitor::Shutdown();
ClosingService::Shutdown();
#endif // !defined(MOZILLA_XPCOMRT_API)
mInitialized = false;
@ -1438,7 +1447,8 @@ nsSocketTransportService::AnalyzeConnection(nsTArray<SocketInfo> *data,
if (context->mHandler->mIsPrivate)
return;
PRFileDesc *aFD = context->mFD;
bool tcp = (PR_GetDescType(aFD) == PR_DESC_SOCKET_TCP);
bool tcp = (PR_GetDescType(PR_GetIdentitiesLayer(aFD, PR_NSPR_IO_LAYER)) ==
PR_DESC_SOCKET_TCP);
PRNetAddr peer_addr;
PR_GetPeerName(aFD, &peer_addr);

View File

@ -28,6 +28,7 @@
#include "nsIDNSRecord.h"
#include "nsIDNSService.h"
#include "nsICancelable.h"
#include "ClosingService.h"
#ifdef MOZ_WIDGET_GONK
#include "NetStatistics.h"
@ -36,7 +37,6 @@
using namespace mozilla::net;
using namespace mozilla;
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
static const uint32_t UDP_PACKET_CHUNK_SIZE = 1400;
//-----------------------------------------------------------------------------
@ -91,191 +91,6 @@ private:
PRSocketOptionData mOpt;
};
//-----------------------------------------------------------------------------
// nsUDPSocketCloseThread
//-----------------------------------------------------------------------------
// A helper class carrying call to PR_Close on nsUDPSocket's FD to a separate
// thread. This may be a workaround for shutdown blocks that are caused by
// serial calls to close on UDP sockets.
// It starts an NSPR thread for each socket and also adds itself as an observer
// to "xpcom-shutdown-threads" notification where we join the thread (if not
// already done). During worktime of the thread the class is also
// self-referenced, since observer service might throw the reference away
// sooner than the thread is actually done.
class nsUDPSocketCloseThread : public nsIObserver
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIOBSERVER
static bool Close(PRFileDesc *aFd);
private:
explicit nsUDPSocketCloseThread(PRFileDesc *aFd);
virtual ~nsUDPSocketCloseThread() { }
bool Begin();
void ThreadFunc();
void AddObserver();
void JoinAndRemove();
static void ThreadFunc(void *aClosure)
{ static_cast<nsUDPSocketCloseThread*>(aClosure)->ThreadFunc(); }
// Socket to close.
PRFileDesc *mFd;
PRThread *mThread;
// Self reference, added before we create the thread, dropped
// after the thread is done (from the thread). No races, since
// mSelf is assigned bofore the thread func is executed and
// released only on the thread func.
nsRefPtr<nsUDPSocketCloseThread> mSelf;
// Telemetry probes.
TimeStamp mBeforeClose;
TimeStamp mAfterClose;
// Active threads (roughly) counter, modified only on the main thread
// and used only for telemetry reports.
static uint32_t sActiveThreadsCount;
// Switches to true on "xpcom-shutdown-threads" notification and since
// then it makes the code fallback to a direct call to PR_Close().
static bool sPastShutdown;
};
uint32_t nsUDPSocketCloseThread::sActiveThreadsCount = 0;
bool nsUDPSocketCloseThread::sPastShutdown = false;
NS_IMPL_ISUPPORTS(nsUDPSocketCloseThread, nsIObserver);
bool
nsUDPSocketCloseThread::Close(PRFileDesc *aFd)
{
if (sPastShutdown) {
return false;
}
nsRefPtr<nsUDPSocketCloseThread> t = new nsUDPSocketCloseThread(aFd);
return t->Begin();
}
nsUDPSocketCloseThread::nsUDPSocketCloseThread(PRFileDesc *aFd)
: mFd(aFd)
, mThread(nullptr)
{
}
bool
nsUDPSocketCloseThread::Begin()
{
// Observer service must be worked with on the main thread only.
// This method is called usually on the socket thread.
// Register us before the thread starts. It may happen the thread is
// done and posts removal event sooner then we would post this event
// after the thread creation.
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(
this, &nsUDPSocketCloseThread::AddObserver);
if (event) {
NS_DispatchToMainThread(event);
}
// Keep us self-referenced during lifetime of the thread.
// Released after the thread is done.
mSelf = this;
mThread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
PR_JOINABLE_THREAD, 4 * 4096);
if (!mThread) {
// This doesn't join since there is no thread, just removes
// this class as an observer.
JoinAndRemove();
mSelf = nullptr;
return false;
}
return true;
}
void
nsUDPSocketCloseThread::AddObserver()
{
MOZ_ASSERT(NS_IsMainThread());
++sActiveThreadsCount;
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) {
obs->AddObserver(this, "xpcom-shutdown-threads", false);
}
}
void
nsUDPSocketCloseThread::JoinAndRemove()
{
// Posted from the particular (this) UDP close socket when it's done
// or from "xpcom-shutdown-threads" notification.
MOZ_ASSERT(NS_IsMainThread());
if (mThread) {
PR_JoinThread(mThread);
mThread = nullptr;
Telemetry::Accumulate(Telemetry::UDP_SOCKET_PARALLEL_CLOSE_COUNT, sActiveThreadsCount);
Telemetry::AccumulateTimeDelta(Telemetry::UDP_SOCKET_CLOSE_TIME, mBeforeClose, mAfterClose);
MOZ_ASSERT(sActiveThreadsCount > 0);
--sActiveThreadsCount;
}
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "xpcom-shutdown-threads");
}
}
NS_IMETHODIMP
nsUDPSocketCloseThread::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *aData)
{
MOZ_ASSERT(NS_IsMainThread());
if (!strcmp(aTopic, "xpcom-shutdown-threads")) {
sPastShutdown = true;
JoinAndRemove();
return NS_OK;
}
MOZ_CRASH("Unexpected observer topic");
return NS_OK;
}
void
nsUDPSocketCloseThread::ThreadFunc()
{
PR_SetCurrentThreadName("UDP socket close");
mBeforeClose = TimeStamp::Now();
PR_Close(mFd);
mFd = nullptr;
mAfterClose = TimeStamp::Now();
// Join and remove the observer on the main thread.
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(
this, &nsUDPSocketCloseThread::JoinAndRemove);
if (event) {
NS_DispatchToMainThread(event);
}
// Thread's done, release the self-reference.
mSelf = nullptr;
}
//-----------------------------------------------------------------------------
// nsUDPOutputStream impl
//-----------------------------------------------------------------------------
@ -457,9 +272,7 @@ nsUDPSocket::nsUDPSocket()
nsUDPSocket::~nsUDPSocket()
{
if (mFD) {
if (!nsUDPSocketCloseThread::Close(mFD)) {
PR_Close(mFD);
}
PR_Close(mFD);
mFD = nullptr;
}
@ -701,9 +514,7 @@ nsUDPSocket::OnSocketDetached(PRFileDesc *fd)
if (mFD)
{
NS_ASSERTION(mFD == fd, "wrong file descriptor");
if (!nsUDPSocketCloseThread::Close(mFD)) {
PR_Close(mFD);
}
PR_Close(mFD);
mFD = nullptr;
}
SaveNetworkStats(true);
@ -844,6 +655,7 @@ nsUDPSocket::InitWithAddress(const NetAddr *aAddr, nsIPrincipal *aPrincipal,
// create proxy via NetworkActivityMonitor
NetworkActivityMonitor::AttachIOLayer(mFD);
ClosingService::AttachIOLayer(mFD);
// wait until AsyncListen is called before polling the socket for
// client connections.

View File

@ -12,6 +12,7 @@
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsNetCID.h"
#include "mozilla/Preferences.h"
#include "prnetdb.h"
using namespace mozilla;

View File

@ -36,6 +36,7 @@
#include "prerr.h"
#include "prerror.h"
#include "NetworkActivityMonitor.h"
#include "ClosingService.h"
using namespace mozilla::net;
@ -144,6 +145,9 @@ void ARTPConnection::MakePortPair(
NetworkActivityMonitor::AttachIOLayer(*rtpSocket);
NetworkActivityMonitor::AttachIOLayer(*rtcpSocket);
ClosingService::AttachIOLayer(*rtpSocket);
ClosingService::AttachIOLayer(*rtcpSocket);
// Reduce the chance of using duplicate port numbers.
srand(time(NULL));
// rand() * 1000 may overflow int type, use long long.

View File

@ -34,6 +34,7 @@
#include "prnetdb.h"
#include "prerr.h"
#include "NetworkActivityMonitor.h"
#include "ClosingService.h"
using namespace mozilla::net;
@ -109,6 +110,7 @@ void ARTPSession::MakeUDPSocket(PRFileDesc **s, unsigned port) {
}
NetworkActivityMonitor::AttachIOLayer(*s);
ClosingService::AttachIOLayer(*s);
PRNetAddr addr;
addr.inet.family = PR_AF_INET;

View File

@ -31,6 +31,7 @@
#include <media/stagefright/MetaData.h>
#include <utils/ByteOrder.h>
#include "ClosingService.h"
#include "NetworkActivityMonitor.h"
using namespace mozilla::net;
@ -64,6 +65,7 @@ ARTPWriter::ARTPWriter(int fd)
}
NetworkActivityMonitor::AttachIOLayer(mSocket);
ClosingService::AttachIOLayer(mSocket);
mRTPAddr.inet.family = PR_AF_INET;

View File

@ -34,6 +34,7 @@
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsNetCID.h"
#include "ClosingService.h"
#include "nsIServiceManager.h"
#include "nsICryptoHash.h"
@ -283,6 +284,7 @@ void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
}
NetworkActivityMonitor::AttachIOLayer(mSocket);
ClosingService::AttachIOLayer(mSocket);
MakeSocketBlocking(mSocket, false);

View File

@ -27,6 +27,7 @@
#include "prnetdb.h"
#include "prerr.h"
#include "NetworkActivityMonitor.h"
#include "ClosingService.h"
using namespace mozilla::net;
@ -44,6 +45,7 @@ UDPPusher::UDPPusher(const char *filename, unsigned port)
}
NetworkActivityMonitor::AttachIOLayer(mSocket);
ClosingService::AttachIOLayer(mSocket);
PRNetAddr addr;
addr.inet.family = PR_AF_INET;

View File

@ -2567,35 +2567,70 @@
"n_buckets": 1000,
"description": "Time spent blocked in PR_ConnectContinue when the offline state has changed in the last 60s (ms)."
},
"PRCLOSE_BLOCKING_TIME_NORMAL": {
"PRCLOSE_TCP_BLOCKING_TIME_NORMAL": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close when we are not shutting down and there has been niether a network nor an offline state change in the last 60s (ms)."
},
"PRCLOSE_BLOCKING_TIME_SHUTDOWN": {
"PRCLOSE_TCP_BLOCKING_TIME_SHUTDOWN": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close during a shutdown (ms)."
},
"PRCLOSE_BLOCKING_TIME_CONNECTIVITY_CHANGE": {
"PRCLOSE_TCP_BLOCKING_TIME_CONNECTIVITY_CHANGE": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close when there has been the connectivity change in the last 60s (ms)."
},
"PRCLOSE_BLOCKING_TIME_LINK_CHANGE": {
"PRCLOSE_TCP_BLOCKING_TIME_LINK_CHANGE": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close when there has been a link change in the last 60s (ms)."
},
"PRCLOSE_BLOCKING_TIME_OFFLINE": {
"PRCLOSE_TCP_BLOCKING_TIME_OFFLINE": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close when the offline state has changed in the last 60s (ms)."
},
"PRCLOSE_UDP_BLOCKING_TIME_NORMAL": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close when we are not shutting down and there has been niether a network nor an offline state change in the last 60s (ms)."
},
"PRCLOSE_UDP_BLOCKING_TIME_SHUTDOWN": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close during a shutdown (ms)."
},
"PRCLOSE_UDP_BLOCKING_TIME_CONNECTIVITY_CHANGE": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close when there has been the connectivity change in the last 60s (ms)."
},
"PRCLOSE_UDP_BLOCKING_TIME_LINK_CHANGE": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
"n_buckets": 1000,
"description": "Time spent blocked in PR_Close when there has been a link change in the last 60s (ms)."
},
"PRCLOSE_UDP_BLOCKING_TIME_OFFLINE": {
"expires_in_version": "never",
"kind": "exponential",
"high": "60000",
@ -8687,20 +8722,6 @@
"kind": "count",
"description": "Count plugin hang notices in e10s"
},
"UDP_SOCKET_PARALLEL_CLOSE_COUNT": {
"expires_in_version": "41",
"kind": "linear",
"high": "20",
"n_buckets": 19,
"description": "Number of concurrent UDP socket closing threads"
},
"UDP_SOCKET_CLOSE_TIME": {
"expires_in_version": "45",
"kind": "exponential",
"high": "60000",
"n_buckets": 30,
"description": "Time PR_Close of a UDP socket taken (ms)"
},
"SERVICE_WORKER_SPAWN_ATTEMPTS": {
"expires_in_version": "50",
"kind": "count",