Files
palemoon27/netwerk/base/ClosingService.cpp
roytam1 bb3c92a4bb import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1229623 - Remove compilation/database.py from mach_bootstrap.py. r=mshal (16de324bd5)
- Bug 1228208 - Make sure ICU flags are prepended before system flags. r=glandium (77a099bb4a)
- Bug 1176968 part 2: Add "requirement flags" field to media query features, and logic for ignoring the feature if requirements aren't met. r=heycam (f2fb438cc7)
- Bug 1176968 part 3: Add support for "-webkit-device-pixel-ratio" media query, along with its min/max variants (behind a pref). r=heycam (d9cf15f3f3)
- Bug 1176968 part 4: Add tests for -webkit-device-pixel-ratio, based on existing -moz tests. r=heycam (7a143f1310)
- Bug 1230863 - Remove unused nsPresContext args from many functions. r=roc. (8f3ca74bb8)
- Add APZ support for mousewheel.acceleration prefs. (bug 1214170 part 1, r=kats) (f9ead80db9)
- Add APZ support for mousewheel delta multiplier prefs. (bug 1214170 part 2, r=kats) (111d111124)
- Bug 1143618 - Follow-up to fix static analysis build bustage. r=me on a CLOSED TREE (57c395593f)
- Bug 1021845 - Before compositing, clip the visible region of a layer to the layer's clip rect. r=mattwoodrow (493ad91934)
- Bug 1152046 - move ClosingService::Start/Shutdown to nsIOService. r=mayhemer (4d078b7611)
- Bug 1226909 part 1: Do security checks in a redirect handler rather than when opening the redirected channel. r=ckerschb (30d23ad2ee)
- Bug 1226909 part 2: Let CORS preflight logic grab information from nsILoadInfo rather than duplicate it. r=ckerschb (04ece9d251)
- Bug 1214361 Test final response types after redirect. r=sicking a=abillings (3f288cae02)
- Bug 1210302 - Part 4: Add automated tests; r=sicking (b43a9a02c4)
- Bug 1226909 part 3: Move logic of when to initiate CORS preflight into channels. Allow CORS preflight to happen when doing a same-origin to cross-origin redirect. r=ckerschb (816498fdb5)
- Bug 1216793 - check against tracking protection list in fetch(). r=gcp (1ddeb07832)
- Bug 1228342 - initialize mTainting by all constructors. r=bkelly (60e63d22bd)
- Bug 1226909 part 4: Make AsyncOpen2 set taining information on channels. Use this information in XHR and fetch(). r=bkelly (3b0bc77efc)
- Bug 1214819. Add support for @crossorigin to <link rel=prefetch> so resources can be prefetched via anonymous CORS, for example. r=hurley (de8b0aef94)
- Bug 1216687: Add nsILoadInfo flags for cookie policies. r=ckerschb (f2634fd5b0)
- Bug 1213443 - Parallelism for <link rel=prefetch> r=bz (f5ee458126)
2023-05-12 10:38:28 +08:00

255 lines
6.1 KiB
C++

/* -*- 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"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
class ClosingLayerSecret
{
public:
explicit ClosingLayerSecret(mozilla::net::ClosingService *aClosingService)
: mClosingService(aClosingService)
{
}
~ClosingLayerSecret()
{
mClosingService = nullptr;
}
RefPtr<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, 32 * 1024);
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);
if (mShutdown) {
// This should not happen.
return;
}
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()
{
PR_SetCurrentThreadName("Closing Service");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
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);
}
}
} //namwspacw mozilla
} //namespace net