From c607dc99ba79d95cfde82ee22a47a8510f8dbee5 Mon Sep 17 00:00:00 2001 From: Alexandre Lissy Date: Tue, 2 Aug 2016 14:54:00 +0200 Subject: [PATCH] Bug 1284674 - Remove NUWA r=cyu MozReview-Commit-ID: GyMRNzOBKw6 --- b2g/app/B2GLoader.cpp | 300 --- b2g/app/moz.build | 4 - b2g/app/nsBrowserApp.cpp | 21 +- b2g/confvars.sh | 2 - b2g/graphene/confvars.sh | 2 - dom/ipc/ContentChild.cpp | 128 +- dom/ipc/ContentChild.h | 3 - dom/ipc/ContentParent.cpp | 353 +-- dom/ipc/ContentParent.h | 60 +- dom/ipc/NuwaChild.cpp | 256 -- dom/ipc/NuwaChild.h | 33 - dom/ipc/NuwaParent.cpp | 260 -- dom/ipc/NuwaParent.h | 73 - dom/ipc/PNuwa.ipdl | 31 - dom/ipc/PreallocatedProcessManager.cpp | 273 --- dom/ipc/PreallocatedProcessManager.h | 8 - dom/ipc/ProcessPriorityManager.cpp | 7 - dom/ipc/TabChild.cpp | 52 - dom/ipc/TabContext.h | 1 + dom/ipc/TabParent.cpp | 3 + dom/ipc/moz.build | 5 - dom/ipc/tests/mochitest.ini | 4 - dom/ipc/tests/test_NuwaProcessCreation.html | 68 - dom/ipc/tests/test_NuwaProcessDeadlock.html | 69 - dom/storage/DOMStorageIPC.cpp | 7 - dom/workers/RuntimeService.cpp | 11 - gfx/layers/ipc/ImageBridgeChild.cpp | 4 - gfx/layers/ipc/SharedBufferManagerChild.cpp | 12 - image/DecodePool.cpp | 19 - ipc/chromium/src/base/process_util_linux.cc | 65 - .../src/chrome/common/child_thread.cc | 18 - ipc/chromium/src/chrome/common/child_thread.h | 4 - ipc/contentproc/moz.build | 2 - ipc/contentproc/plugin-container.cpp | 31 +- ipc/glue/BackgroundChildImpl.cpp | 17 - ipc/glue/BackgroundChildImpl.h | 6 - ipc/glue/BackgroundParentImpl.cpp | 21 - ipc/glue/BackgroundParentImpl.h | 9 - ipc/glue/GeckoChildProcessHost.cpp | 53 - ipc/glue/GeckoChildProcessHost.h | 22 - ipc/glue/MessageChannel.h | 12 - ipc/glue/MessageLink.cpp | 67 - ipc/glue/MessageLink.h | 19 - ipc/glue/MessagePump.cpp | 18 +- ipc/glue/PBackground.ipdl | 4 - ipc/glue/ProcessUtils.h | 15 - ipc/glue/ProcessUtils_linux.cpp | 603 ----- js/src/old-configure.in | 4 - js/src/vm/HelperThreads.cpp | 14 - js/xpconnect/src/XPCJSRuntime.cpp | 11 - layout/base/nsRefreshDriver.cpp | 13 - memory/jemalloc/moz.build | 3 - memory/mozjemalloc/moz.build | 3 - memory/replace/dmd/DMD.cpp | 5 - memory/replace/logalloc/replay/Replay.cpp | 12 - mozglue/build/Nuwa.cpp | 2104 ----------------- mozglue/build/Nuwa.h | 201 -- mozglue/build/moz.build | 8 - netwerk/base/Predictor.cpp | 25 - netwerk/base/nsPACMan.cpp | 8 - netwerk/base/nsSocketTransportService2.cpp | 10 - netwerk/base/nsStreamTransportService.cpp | 39 - .../linux/nsNotifyAddrListener_Linux.cpp | 22 - old-configure.in | 23 - security/sandbox/linux/Sandbox.cpp | 13 +- security/sandbox/linux/Sandbox.h | 2 +- toolkit/components/extensions/Extension.jsm | 4 - toolkit/modules/AppConstants.jsm | 7 - toolkit/xre/moz.build | 3 - toolkit/xre/nsAppRunner.cpp | 8 - toolkit/xre/nsEmbedFunctions.cpp | 42 - tools/profiler/core/ThreadInfo.h | 4 - tools/profiler/core/platform-linux.cc | 42 - widget/gonk/GonkMemoryPressureMonitoring.cpp | 10 - widget/gonk/nsAppShell.cpp | 9 - xpcom/base/nsCycleCollector.cpp | 4 - xpcom/base/nsMemoryReporterManager.cpp | 8 +- xpcom/build/nsXULAppAPI.h | 12 - xpcom/components/ManifestParser.cpp | 31 +- xpcom/components/nsComponentManager.cpp | 89 - xpcom/components/nsComponentManager.h | 29 - xpcom/threads/BackgroundHangMonitor.cpp | 9 - xpcom/threads/HangMonitor.cpp | 10 - xpcom/threads/TimerThread.cpp | 16 +- xpcom/threads/nsThread.cpp | 10 - xpcom/threads/nsTimerImpl.cpp | 3 - 86 files changed, 23 insertions(+), 5902 deletions(-) delete mode 100644 b2g/app/B2GLoader.cpp delete mode 100644 dom/ipc/NuwaChild.cpp delete mode 100644 dom/ipc/NuwaChild.h delete mode 100644 dom/ipc/NuwaParent.cpp delete mode 100644 dom/ipc/NuwaParent.h delete mode 100644 dom/ipc/PNuwa.ipdl delete mode 100644 dom/ipc/tests/test_NuwaProcessCreation.html delete mode 100644 dom/ipc/tests/test_NuwaProcessDeadlock.html delete mode 100644 mozglue/build/Nuwa.cpp delete mode 100644 mozglue/build/Nuwa.h diff --git a/b2g/app/B2GLoader.cpp b/b2g/app/B2GLoader.cpp deleted file mode 100644 index f50cadc13b2aa..0000000000000 --- a/b2g/app/B2GLoader.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=2 autoindent cindent expandtab: */ -/* 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 "nsXULAppAPI.h" -#include "application.ini.h" -#include "nsXPCOMGlue.h" -#include "nsStringGlue.h" -#include "nsCOMPtr.h" -#include "nsIFile.h" -#include "BinaryPath.h" - -#include -#include -#include -#include -#include -#include - -#include - -#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL -#include "mozilla/UniquePtr.h" - -#define ASSERT(x) if (!(x)) { MOZ_CRASH(); } - -// Functions being loaded by XPCOMGlue -XRE_ProcLoaderServiceRunType XRE_ProcLoaderServiceRun; -XRE_ProcLoaderClientInitType XRE_ProcLoaderClientInit; -XRE_ProcLoaderPreloadType XRE_ProcLoaderPreload; -extern XRE_CreateAppDataType XRE_CreateAppData; -extern XRE_GetFileFromPathType XRE_GetFileFromPath; - -static const nsDynamicFunctionLoad kXULFuncs[] = { - { "XRE_ProcLoaderServiceRun", (NSFuncPtr*) &XRE_ProcLoaderServiceRun }, - { "XRE_ProcLoaderClientInit", (NSFuncPtr*) &XRE_ProcLoaderClientInit }, - { "XRE_ProcLoaderPreload", (NSFuncPtr*) &XRE_ProcLoaderPreload }, - { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData }, - { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath }, - { nullptr, nullptr } -}; - -typedef mozilla::Vector FdArray; -static const int kReservedFileDescriptors = 5; -static const int kBeginReserveFileDescriptor = STDERR_FILENO + 1; - -static int -GetDirnameSlash(const char *aPath, char *aOutDir, int aMaxLen) -{ - char *lastSlash = strrchr(aPath, XPCOM_FILE_PATH_SEPARATOR[0]); - if (lastSlash == nullptr) { - return 0; - } - int cpsz = lastSlash - aPath + 1; // include slash - if (aMaxLen <= cpsz) { - return 0; - } - strncpy(aOutDir, aPath, cpsz); - aOutDir[cpsz] = 0; - return cpsz; -} - -static bool -GetXPCOMPath(const char *aProgram, char *aOutPath, int aMaxLen) -{ - auto progBuf = mozilla::MakeUnique(aMaxLen); - nsresult rv = mozilla::BinaryPath::Get(aProgram, progBuf.get()); - NS_ENSURE_SUCCESS(rv, false); - - int len = GetDirnameSlash(progBuf.get(), aOutPath, aMaxLen); - NS_ENSURE_TRUE(!!len, false); - - NS_ENSURE_TRUE((len + sizeof(XPCOM_DLL)) < (unsigned)aMaxLen, false); - char *afterSlash = aOutPath + len; - strcpy(afterSlash, XPCOM_DLL); - return true; -} - -static bool -LoadLibxul(const char *aXPCOMPath) -{ - nsresult rv; - - XPCOMGlueEnablePreload(); - rv = XPCOMGlueStartup(aXPCOMPath); - NS_ENSURE_SUCCESS(rv, false); - - rv = XPCOMGlueLoadXULFunctions(kXULFuncs); - NS_ENSURE_SUCCESS(rv, false); - - return true; -} - -/** - * Return true if |arg| matches the given argument name. - */ -static bool -IsArg(const char* arg, const char* s) -{ - if (*arg == '-') { - if (*++arg == '-') { - ++arg; - } - return !strcasecmp(arg, s); - } - -#if defined(XP_WIN) - if (*arg == '/') { - return !strcasecmp(++arg, s); - } -#endif - - return false; -} - -static already_AddRefed -GetAppIni(int argc, const char *argv[]) -{ - nsCOMPtr appini; - nsresult rv; - - // Allow firefox.exe to launch XULRunner apps via -app - // Note that -app must be the *first* argument. - const char *appDataFile = getenv("XUL_APP_FILE"); - if (appDataFile && *appDataFile) { - rv = XRE_GetFileFromPath(appDataFile, getter_AddRefs(appini)); - NS_ENSURE_SUCCESS(rv, nullptr); - } else if (argc > 1 && IsArg(argv[1], "app")) { - if (argc == 2) { - return nullptr; - } - - rv = XRE_GetFileFromPath(argv[2], getter_AddRefs(appini)); - NS_ENSURE_SUCCESS(rv, nullptr); - - char appEnv[MAXPATHLEN]; - snprintf(appEnv, MAXPATHLEN, "XUL_APP_FILE=%s", argv[2]); - if (putenv(strdup(appEnv))) { - return nullptr; - } - } - - return appini.forget(); -} - -static bool -LoadStaticData(int argc, const char *argv[]) -{ - char xpcomPath[MAXPATHLEN]; - bool ok = GetXPCOMPath(argv[0], xpcomPath, MAXPATHLEN); - NS_ENSURE_TRUE(ok, false); - - ok = LoadLibxul(xpcomPath); - NS_ENSURE_TRUE(ok, false); - - char progDir[MAXPATHLEN]; - ok = GetDirnameSlash(xpcomPath, progDir, MAXPATHLEN); - NS_ENSURE_TRUE(ok, false); - - nsCOMPtr appini = GetAppIni(argc, argv); - const nsXREAppData *appData; - if (appini) { - nsresult rv = - XRE_CreateAppData(appini, const_cast(&appData)); - NS_ENSURE_SUCCESS(rv, false); - } else { - appData = &sAppData; - } - - XRE_ProcLoaderPreload(progDir, appData); - - if (appini) { - XRE_FreeAppData(const_cast(appData)); - } - - return true; -} - -/** - * Fork and run parent and child process. - * - * The parent is the b2g process and child for Nuwa. - */ -static int -RunProcesses(int argc, const char *argv[], FdArray& aReservedFds) -{ - /* - * The original main() of the b2g process. It is renamed to - * b2g_main() for the b2g loader. - */ - int b2g_main(int argc, const char *argv[]); - - int ipcSockets[2] = {-1, -1}; - int r = socketpair(AF_LOCAL, SOCK_STREAM, 0, ipcSockets); - ASSERT(r == 0); - int parentSock = ipcSockets[0]; - int childSock = ipcSockets[1]; - - r = fcntl(parentSock, F_SETFL, O_NONBLOCK); - ASSERT(r != -1); - r = fcntl(childSock, F_SETFL, O_NONBLOCK); - ASSERT(r != -1); - - pid_t pid = fork(); - ASSERT(pid >= 0); - bool isChildProcess = pid == 0; - - close(isChildProcess ? parentSock : childSock); - - if (isChildProcess) { - /* The Nuwa process */ - /* This provides the IPC service of loading Nuwa at the process. - * The b2g process would send a IPC message of loading Nuwa - * as the replacement of forking and executing plugin-container. - */ - return XRE_ProcLoaderServiceRun(getppid(), childSock, argc, argv, - aReservedFds); - } - - // Reap zombie child process. - struct sigaction sa; - sa.sa_handler = SIG_IGN; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGCHLD, &sa, nullptr); - - // The b2g process - int childPid = pid; - XRE_ProcLoaderClientInit(childPid, parentSock, aReservedFds); - return b2g_main(argc, argv); -} - -/** - * Reserve the file descriptors that shouldn't be taken for other use for the - * child process. - */ -static void -ReserveFileDescriptors(FdArray& aReservedFds) -{ - for (int i = 0; i < kReservedFileDescriptors; i++) { - struct stat fileState; - int target = kBeginReserveFileDescriptor + i; - if (fstat(target, &fileState) == 0) { - MOZ_CRASH("ProcLoader error: a magic file descriptor is occupied."); - } - - int fd = open("/dev/null", O_RDWR); - if (fd == -1) { - MOZ_CRASH("ProcLoader error: failed to reserve a magic file descriptor."); - } - - if (!aReservedFds.append(target)) { - MOZ_CRASH("Failed to append to aReservedFds"); - } - - if (fd == target) { - // No need to call dup2(). We already occupy the desired file descriptor. - continue; - } - - if (dup2(fd, target)) { - MOZ_CRASH("ProcLoader error: failed to reserve a magic file descriptor."); - } - - close(fd); - } -} - -/** - * B2G Loader is responsible for loading the b2g process and the - * Nuwa process. It forks into the parent process, for the b2g - * process, and the child process, for the Nuwa process. - * - * The loader loads libxul and performs initialization of static data - * before forking, so relocation of libxul and static data can be - * shared between the b2g process, the Nuwa process, and the content - * processes. - */ -int -main(int argc, const char* argv[]) -{ - /** - * Reserve file descriptors before loading static data. - */ - FdArray reservedFds; - ReserveFileDescriptors(reservedFds); - - /* - * Before fork(), libxul and static data of Gecko are loaded for - * sharing. - */ - bool ok = LoadStaticData(argc, argv); - if (!ok) { - return 255; - } - - return RunProcesses(argc, argv, reservedFds); -} diff --git a/b2g/app/moz.build b/b2g/app/moz.build index b9069800155f8..b28889065fef6 100644 --- a/b2g/app/moz.build +++ b/b2g/app/moz.build @@ -8,10 +8,6 @@ if CONFIG['GAIADIR']: GeckoProgram(CONFIG['MOZ_APP_NAME'] + "-bin") else: GeckoProgram(CONFIG['MOZ_APP_NAME']) -if CONFIG['MOZ_B2G_LOADER']: - SOURCES += [ - 'B2GLoader.cpp', - ] SOURCES += [ 'nsBrowserApp.cpp', diff --git a/b2g/app/nsBrowserApp.cpp b/b2g/app/nsBrowserApp.cpp index 5fb29a46461af..20b8a4c3f9fb0 100644 --- a/b2g/app/nsBrowserApp.cpp +++ b/b2g/app/nsBrowserApp.cpp @@ -163,22 +163,9 @@ static int do_main(int argc, char* argv[]) return XRE_main(argc, argv, &sAppData, 0); } -#ifdef MOZ_B2G_LOADER -/* - * The main() in B2GLoader.cpp is the new main function instead of the - * main() here if it is enabled. So, rename it to b2g_man(). - */ -#define main b2g_main -#define _CONST const -#else -#define _CONST -#endif - -int main(int argc, _CONST char* argv[]) +int main(int argc, char* argv[]) { -#ifndef MOZ_B2G_LOADER char exePath[MAXPATHLEN]; -#endif #ifdef MOZ_WIDGET_GONK // This creates a ThreadPool for binder ipc. A ThreadPool is necessary to @@ -189,7 +176,6 @@ int main(int argc, _CONST char* argv[]) #endif nsresult rv; -#ifndef MOZ_B2G_LOADER rv = mozilla::BinaryPath::Get(argv[0], exePath); if (NS_FAILED(rv)) { Output("Couldn't calculate the application directory.\n"); @@ -201,7 +187,6 @@ int main(int argc, _CONST char* argv[]) return 255; strcpy(++lastSlash, XPCOM_DLL); -#endif // MOZ_B2G_LOADER #if defined(XP_UNIX) // If the b2g app is launched from adb shell, then the shell will wind @@ -216,9 +201,6 @@ int main(int argc, _CONST char* argv[]) DllBlocklist_Initialize(); #endif - // B2G loader has already initialized Gecko so we can't initialize - // it again here. -#ifndef MOZ_B2G_LOADER // We do this because of data in bug 771745 XPCOMGlueEnablePreload(); @@ -229,7 +211,6 @@ int main(int argc, _CONST char* argv[]) } // Reset exePath so that it is the directory name and not the xpcom dll name *lastSlash = 0; -#endif // MOZ_B2G_LOADER rv = XPCOMGlueLoadXULFunctions(kXULFuncs); if (NS_FAILED(rv)) { diff --git a/b2g/confvars.sh b/b2g/confvars.sh index 9e75bb3f554a2..8068f2e142b0e 100644 --- a/b2g/confvars.sh +++ b/b2g/confvars.sh @@ -53,8 +53,6 @@ MOZ_TOOLKIT_SEARCH= MOZ_B2G=1 if test "$OS_TARGET" = "Android"; then -MOZ_NUWA_PROCESS=1 -MOZ_B2G_LOADER=1 MOZ_ENABLE_WARNINGS_AS_ERRORS=1 fi diff --git a/b2g/graphene/confvars.sh b/b2g/graphene/confvars.sh index 5ad22fcd171ae..fdd286db45194 100644 --- a/b2g/graphene/confvars.sh +++ b/b2g/graphene/confvars.sh @@ -48,8 +48,6 @@ MOZ_PLACES= MOZ_B2G=1 if test "$OS_TARGET" = "Android"; then -MOZ_NUWA_PROCESS=1 -MOZ_B2G_LOADER=1 MOZ_ENABLE_WARNINGS_AS_ERRORS=1 fi diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index ca5019af9fb27..fa227e23fa58c 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -166,11 +166,6 @@ #include "nsIAccessibilityService.h" #endif -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif -#include "NuwaChild.h" - #ifndef MOZ_SIMPLEPUSH #include "mozilla/dom/PushNotifier.h" #endif @@ -516,57 +511,6 @@ NS_IMPL_ISUPPORTS(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback) ContentChild* ContentChild::sSingleton; -// Performs initialization that is not fork-safe, i.e. that must be done after -// forking from the Nuwa process. -void -InitOnContentProcessCreated() -{ -#ifdef MOZ_NUWA_PROCESS - // Wait until we are forked from Nuwa - if (IsNuwaProcess()) { - return; - } - - nsCOMPtr permManager = services::GetPermissionManager(); - MOZ_ASSERT(permManager, "Unable to get permission manager"); - nsresult rv = permManager->RefreshPermission(); - if (NS_FAILED(rv)) { - MOZ_ASSERT(false, "Failed updating permission in child process"); - } -#endif - - // This will register cross-process observer. - mozilla::dom::time::InitializeDateCacheCleaner(); -} - -#ifdef MOZ_NUWA_PROCESS -static void -ResetTransports(void* aUnused) -{ - ContentChild* child = ContentChild::GetSingleton(); - mozilla::ipc::Transport* transport = child->GetTransport(); - int fd = transport->GetFileDescriptor(); - transport->ResetFileDescriptor(fd); - - nsTArray actors; - child->GetOpenedActors(actors); - for (size_t i = 0; i < actors.Length(); i++) { - IToplevelProtocol* toplevel = actors[i]; - transport = toplevel->GetTransport(); - fd = transport->GetFileDescriptor(); - transport->ResetFileDescriptor(fd); - } -} -#endif - -#if defined(MOZ_TASK_TRACER) && defined(MOZ_NUWA_PROCESS) -static void -ReinitTaskTracer(void* /*aUnused*/) -{ - mozilla::tasktracer::InitTaskTracer(mozilla::tasktracer::FORKED_AFTER_NUWA); -} -#endif - ContentChild::ContentChild() : mID(uint64_t(-1)) , mCanOverrideProcessName(true) @@ -642,11 +586,7 @@ ContentChild::Init(MessageLoop* aIOLoop, // If communications with the parent have broken down, take the process // down so it's not hanging around. - bool abortOnError = true; -#ifdef MOZ_NUWA_PROCESS - abortOnError &= !IsNuwaProcess(); -#endif - GetIPCChannel()->SetAbortOnError(abortOnError); + GetIPCChannel()->SetAbortOnError(true); #ifdef MOZ_X11 // Send the parent our X socket to act as a proxy reference for our X @@ -663,17 +603,6 @@ ContentChild::Init(MessageLoop* aIOLoop, SendGetProcessAttributes(&mID, &mIsForApp, &mIsForBrowser); InitProcessAttributes(); -#if defined(MOZ_TASK_TRACER) && defined (MOZ_NUWA_PROCESS) - if (IsNuwaProcess()) { - NuwaAddConstructor(ReinitTaskTracer, nullptr); - } -#endif - -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaAddConstructor(ResetTransports, nullptr); - } -#endif #ifdef NS_PRINTING // Force the creation of the nsPrintingProxy so that it's IPC counterpart, // PrintingParent, is always available for printing initiated from the parent. @@ -687,12 +616,6 @@ void ContentChild::InitProcessAttributes() { #ifdef MOZ_WIDGET_GONK -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - SetProcessName(NS_LITERAL_STRING("(Nuwa)"), false); - return; - } -#endif if (mIsForApp && !mIsForBrowser) { SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false); } else { @@ -1037,7 +960,8 @@ ContentChild::InitXPCOM() global->SetInitialProcessData(data); } - InitOnContentProcessCreated(); + // This will register cross-process observer. + mozilla::dom::time::InitializeDateCacheCleaner(); } PMemoryReportRequestChild* @@ -2282,14 +2206,6 @@ ContentChild::ActorDestroy(ActorDestroyReason why) } mIsAlive = false; -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - // The Nuwa cannot go through the full XPCOM shutdown path or deadlock - // will result. - ProcessChild::QuickExit(); - } -#endif - XRE_ShutdownChildProcess(); #endif // NS_FREE_PERMANENT_DATA } @@ -2528,9 +2444,6 @@ ContentChild::RecvAddPermission(const IPC::Permission& permission) bool ContentChild::RecvFlushMemory(const nsString& reason) { -#ifdef MOZ_NUWA_PROCESS - MOZ_ASSERT(!IsNuwaProcess() || !IsNuwaReady()); -#endif nsCOMPtr os = mozilla::services::GetObserverService(); if (os) { @@ -2575,31 +2488,6 @@ ContentChild::RecvCycleCollect() return true; } -#ifdef MOZ_NUWA_PROCESS -static void -OnFinishNuwaPreparation() -{ - // We want to ensure that the PBackground actor gets cloned in the Nuwa - // process before we freeze. Also, we have to do this to avoid deadlock. - // Protocols that are "opened" (e.g. PBackground, PCompositorBridge) block - // the main thread to wait for the IPC thread during the open operation. - // NuwaSpawnWait() blocks the IPC thread to wait for the main thread when - // the Nuwa process is forked. Unless we ensure that the two cannot happen - // at the same time then we risk deadlock. Spinning the event loop here - // guarantees the ordering is safe for PBackground. - while (!BackgroundChild::GetForCurrentThread()) { - if (NS_WARN_IF(!NS_ProcessNextEvent())) { - return; - } - } - - // This will create the actor. - Unused << mozilla::dom::NuwaChild::GetSingleton(); - - MakeNuwaProcess(); -} -#endif - static void PreloadSlowThings() { @@ -2644,13 +2532,6 @@ ContentChild::RecvAppInit() PreloadSlowThings(); } -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - ContentChild::GetSingleton()->RecvGarbageCollect(); - MessageLoop::current()->PostTask(NewRunnableFunction(OnFinishNuwaPreparation)); - } -#endif - return true; } @@ -2796,9 +2677,6 @@ ContentChild::RecvNotifyProcessPriorityChanged( bool ContentChild::RecvMinimizeMemoryUsage() { -#ifdef MOZ_NUWA_PROCESS - MOZ_ASSERT(!IsNuwaProcess() || !IsNuwaReady()); -#endif nsCOMPtr mgr = do_GetService("@mozilla.org/memory-reporter-manager;1"); NS_ENSURE_TRUE(mgr, true); diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index e701d67333db7..acc44f0ae58a0 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -689,9 +689,6 @@ class ContentChild final : public PContentChild DISALLOW_EVIL_CONSTRUCTORS(ContentChild); }; -void -InitOnContentProcessCreated(); - uint64_t NextWindowID(); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index fbfe28b5a1939..f821ceea960c0 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -52,7 +52,6 @@ #include "mozilla/dom/MediaKeySystemAccess.h" #endif #include "mozilla/dom/Notification.h" -#include "mozilla/dom/NuwaParent.h" #include "mozilla/dom/PContentBridgeParent.h" #include "mozilla/dom/PContentPermissionRequestParent.h" #include "mozilla/dom/PCycleCollectWithLogsParent.h" @@ -326,11 +325,6 @@ const nsIID nsIConsoleService::COMTypeInfo::kIID = NS_IC namespace mozilla { namespace dom { -#ifdef MOZ_NUWA_PROCESS -int32_t ContentParent::sNuwaPid = 0; -bool ContentParent::sNuwaReady = false; -#endif - #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline" #define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity" @@ -549,11 +543,6 @@ StaticAutoPtr > ContentParent::sContentParents; UniquePtr ContentParent::sSandboxBrokerPolicyFactory; #endif -#ifdef MOZ_NUWA_PROCESS -// The pref updates sent to the Nuwa process. -static nsTArray* sNuwaPrefUpdates; -#endif - // This is true when subprocess launching is enabled. This is the // case between StartUp() and ShutDown() or JoinAllSubprocesses(). static bool sCanLaunchSubprocesses; @@ -601,45 +590,6 @@ static const char* sObserverTopics[] = { "gmp-changed", }; -#ifdef MOZ_NUWA_PROCESS -// Contains the observer topics that can be sent to the Nuwa process after it -// becomes ready. The ContentParent instance will unregister sObserverTopics -// if not listed in sNuwaSafeObserverTopics. -static const char* sNuwaSafeObserverTopics[] = { - "xpcom-shutdown", - "profile-before-change", -#ifdef MOZ_WIDGET_GONK - "phone-state-changed", -#endif -#ifdef ACCESSIBILITY - "a11y-init-or-shutdown", -#endif - "nsPref:Changed" -}; -#endif -/* static */ already_AddRefed -ContentParent::RunNuwaProcess() -{ - MOZ_ASSERT(NS_IsMainThread()); - RefPtr nuwaProcess = - new ContentParent(/* aApp = */ nullptr, - /* aOpener = */ nullptr, - /* aIsForBrowser = */ false, - /* aIsForPreallocated = */ true, - /* aIsNuwaProcess = */ true); - - if (!nuwaProcess->LaunchSubprocess(PROCESS_PRIORITY_BACKGROUND)) { - return nullptr; - } - - nuwaProcess->Init(); -#ifdef MOZ_NUWA_PROCESS - sNuwaPid = nuwaProcess->Pid(); - sNuwaReady = false; -#endif - return nuwaProcess.forget(); -} - // PreallocateAppProcess is called by the PreallocatedProcessManager. // ContentParent then takes this process back within // GetNewOrPreallocatedAppProcess. @@ -691,8 +641,6 @@ ContentParent::GetNewOrPreallocatedAppProcess(mozIApplication* aApp, } } - // XXXkhuey Nuwa wants the frame loader to try again later, but the - // frame loader is really not set up to do that ... NS_WARNING("Unable to use pre-allocated app process"); process = new ContentParent(aApp, /* aOpener = */ aOpener, @@ -912,11 +860,7 @@ ContentParent::SendAsyncUpdate(nsIWidget* aWidget) bool ContentParent::PreallocatedProcessReady() { -#ifdef MOZ_NUWA_PROCESS - return PreallocatedProcessManager::PreallocatedProcessReady(); -#else return true; -#endif } bool @@ -1534,10 +1478,7 @@ ContentParent::SetPriorityAndCheckIsAlive(ProcessPriority aPriority) // // Bug 943174: use waitid() with WNOWAIT so that, if the process // did exit, we won't consume its zombie and confuse the - // GeckoChildProcessHost dtor. Also, if the process isn't a - // direct child because of Nuwa this will fail with ECHILD, and we - // need to assume the child is alive in that case rather than - // assuming it's dead (as is otherwise a reasonable fallback). + // GeckoChildProcessHost dtor. #ifdef MOZ_WIDGET_GONK siginfo_t info; info.si_pid = 0; @@ -1598,14 +1539,6 @@ ContentParent::TransformPreallocatedIntoBrowser(ContentParent* aOpener) void ContentParent::ShutDownProcess(ShutDownMethod aMethod) { -#ifdef MOZ_NUWA_PROCESS - if (aMethod == SEND_SHUTDOWN_MESSAGE && IsNuwaProcess()) { - // We shouldn't send shutdown messages to frozen Nuwa processes, - // so just close the channel. - aMethod = CLOSE_CHANNEL; - } -#endif - // Shutting down by sending a shutdown message works differently than the // other methods. We first call Shutdown() in the child. After the child is // ready, it calls FinishShutdown() on us. Then we close the channel. @@ -1635,13 +1568,6 @@ ContentParent::ShutDownProcess(ShutDownMethod aMethod) // sequence. mCalledClose = true; Close(); -#ifdef MOZ_NUWA_PROCESS - // Kill Nuwa process forcibly to break its IPC channels and finalize - // corresponding parents. - if (IsNuwaProcess()) { - KillHard("ShutDownProcess"); - } -#endif } const ManagedContainer& ocuParents = @@ -1724,10 +1650,6 @@ void ContentParent::OnChannelError() { RefPtr content(this); -#ifdef MOZ_NUWA_PROCESS - // Handle app or Nuwa process exit before normal channel error handling. - PreallocatedProcessManager::MaybeForgetSpare(this); -#endif PContentParent::OnChannelError(); } @@ -1929,14 +1851,6 @@ ContentParent::ActorDestroy(ActorDestroyReason why) // remove the global remote preferences observers Preferences::RemoveObserver(this, ""); -#ifdef MOZ_NUWA_PROCESS - // Remove the pref update requests. - if (IsNuwaProcess() && sNuwaPrefUpdates) { - delete sNuwaPrefUpdates; - sNuwaPrefUpdates = nullptr; - } -#endif - RecvRemoveGeolocationListener(); mConsoleService = nullptr; @@ -2198,10 +2112,6 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER); std::vector extraArgs; - if (mIsNuwaProcess) { - extraArgs.push_back("-nuwa"); - } - if (!mSubprocess->LaunchAndWaitForProcessHandle(extraArgs)) { MarkAsDead(); return false; @@ -2227,12 +2137,10 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR ContentParent::ContentParent(mozIApplication* aApp, ContentParent* aOpener, bool aIsForBrowser, - bool aIsForPreallocated, - bool aIsNuwaProcess /* = false */) + bool aIsForPreallocated) : nsIContentParent() , mOpener(aOpener) , mIsForBrowser(aIsForBrowser) - , mIsNuwaProcess(aIsNuwaProcess) { InitializeMembers(); // Perform common initialization. @@ -2240,20 +2148,13 @@ ContentParent::ContentParent(mozIApplication* aApp, // true. MOZ_ASSERT(!!aApp + aIsForBrowser + aIsForPreallocated <= 1); - // Only the preallocated process uses Nuwa. - MOZ_ASSERT_IF(aIsNuwaProcess, aIsForPreallocated); - - if (!aIsNuwaProcess && !aIsForPreallocated) { - mMetamorphosed = true; - } + mMetamorphosed = true; // Insert ourselves into the global linked list of ContentParent objects. if (!sContentParents) { sContentParents = new LinkedList(); } - if (!aIsNuwaProcess) { - sContentParents->insertBack(this); - } + sContentParents->insertBack(this); if (aApp) { aApp->GetManifestURL(mAppManifestURL); @@ -2274,83 +2175,10 @@ ContentParent::ContentParent(mozIApplication* aApp, #endif NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - ChildPrivileges privs = aIsNuwaProcess - ? base::PRIVILEGES_INHERIT - : base::PRIVILEGES_DEFAULT; + ChildPrivileges privs = base::PRIVILEGES_DEFAULT; mSubprocess = new GeckoChildProcessHost(GeckoProcessType_Content, privs); } -#ifdef MOZ_NUWA_PROCESS -static const mozilla::ipc::FileDescriptor* -FindFdProtocolFdMapping(const nsTArray& aFds, - ProtocolId aProtoId) -{ - for (unsigned int i = 0; i < aFds.Length(); i++) { - if (aFds[i].protocolId() == aProtoId) { - return &aFds[i].fd(); - } - } - return nullptr; -} - -/** - * This constructor is used for new content process cloned from a template. - * - * For Nuwa. - */ -ContentParent::ContentParent(ContentParent* aTemplate, - const nsAString& aAppManifestURL, - base::ProcessHandle aPid, - InfallibleTArray&& aFds) - : mAppManifestURL(aAppManifestURL) - , mIsForBrowser(false) - , mIsNuwaProcess(false) -{ - InitializeMembers(); // Perform common initialization. - - sContentParents->insertBack(this); - - // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the - // PID along with the warning. - nsDebugImpl::SetMultiprocessMode("Parent"); - - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - const FileDescriptor* fd = FindFdProtocolFdMapping(aFds, GetProtocolId()); - - NS_ASSERTION(fd != nullptr, "IPC Channel for PContent is necessary!"); - mSubprocess = new GeckoExistingProcessHost(GeckoProcessType_Content, - aPid, *fd); - - mSubprocess->LaunchAndWaitForProcessHandle(); - - // Clone actors routed by aTemplate for this instance. - ProtocolCloneContext cloneContext; - cloneContext.SetContentParent(this); - CloneManagees(aTemplate, &cloneContext); - CloneOpenedToplevels(aTemplate, aFds, aPid, &cloneContext); - - Open(mSubprocess->GetChannel(), - base::GetProcId(mSubprocess->GetChildProcessHandle())); - - // Set the subprocess's priority (bg if we're a preallocated process, fg - // otherwise). We do this first because we're likely /lowering/ its CPU and - // memory priority, which it has inherited from this process. - ProcessPriority priority; - if (IsPreallocated()) { - priority = PROCESS_PRIORITY_PREALLOC; - } else { - priority = PROCESS_PRIORITY_FOREGROUND; - } - - InitInternal(priority, - false, /* Setup Off-main thread compositing */ - false /* Send registered chrome */); - - ContentProcessManager::GetSingleton()->AddContentProcess(this); -} -#endif // MOZ_NUWA_PROCESS - ContentParent::~ContentParent() { if (mForceKillTimer) { @@ -2372,13 +2200,6 @@ ContentParent::~ContentParent() MOZ_ASSERT(!sAppContentParents || sAppContentParents->Get(mAppManifestURL) != this); } - -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - sNuwaReady = false; - sNuwaPid = 0; - } -#endif } void @@ -2491,11 +2312,6 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority, #ifdef MOZ_CONTENT_SANDBOX bool shouldSandbox = true; -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - shouldSandbox = false; - } -#endif MaybeFileDesc brokerFd = void_t(); #ifdef XP_LINUX // XXX: Checking the pref here makes it possible to enable/disable sandboxing @@ -2566,14 +2382,6 @@ ContentParent::IsForApp() const return !mAppManifestURL.IsEmpty(); } -#ifdef MOZ_NUWA_PROCESS -bool -ContentParent::IsNuwaProcess() const -{ - return mIsNuwaProcess; -} -#endif - int32_t ContentParent::Pid() const { @@ -2880,125 +2688,6 @@ ContentParent::RecvAudioChannelServiceStatus( return true; } -void -ContentParent::ForkNewProcess(bool aBlocking) -{ -#ifdef MOZ_NUWA_PROCESS - uint32_t pid; - auto fds = MakeUnique>(); - - MOZ_ASSERT(IsNuwaProcess() && mNuwaParent); - - if (mNuwaParent->ForkNewProcess(pid, mozilla::Move(fds), aBlocking)) { - OnNewProcessCreated(pid, mozilla::Move(fds)); - } -#else - NS_ERROR("ContentParent::ForkNewProcess() not implemented!"); -#endif -} - -#ifdef MOZ_NUWA_PROCESS -// Keep only observer topics listed in sNuwaSafeObserverTopics and unregister -// all the other registered topics. -static void -KeepNuwaSafeObserverTopics(ContentParent* aNuwaContentParent) -{ - MOZ_ASSERT(aNuwaContentParent && aNuwaContentParent->IsNuwaProcess()); - - nsCOMPtr obs = mozilla::services::GetObserverService(); - if (!obs) { - return; - } - - size_t topicLength = ArrayLength(sObserverTopics); - for (size_t i = 0; i < topicLength; ++i) { - bool nuwaSafe = false; - size_t safeTopicLength = ArrayLength(sNuwaSafeObserverTopics); - - for (size_t j = 0; j < safeTopicLength; j++) { - if (!nsCRT::strcmp(sObserverTopics[i], - sNuwaSafeObserverTopics[j])) { - // In the whitelist: don't need to unregister. - nuwaSafe = true; - break; - } - } - - if (!nuwaSafe) { - obs->RemoveObserver(aNuwaContentParent, sObserverTopics[i]); - } - } -} -#endif - -void -ContentParent::OnNuwaReady() -{ -#ifdef MOZ_NUWA_PROCESS - // Protection from unauthorized IPC message is done in PNuwa protocol. - // Just assert that this actor is really for the Nuwa process. - MOZ_ASSERT(IsNuwaProcess()); - - sNuwaReady = true; - KeepNuwaSafeObserverTopics(this); - - PreallocatedProcessManager::OnNuwaReady(); - return; -#else - NS_ERROR("ContentParent::OnNuwaReady() not implemented!"); - return; -#endif -} - -void -ContentParent::OnNewProcessCreated(uint32_t aPid, - UniquePtr>&& aFds) -{ -#ifdef MOZ_NUWA_PROCESS - // Protection from unauthorized IPC message is done in PNuwa protocol. - // Just assert that this actor is really for the Nuwa process. - MOZ_ASSERT(IsNuwaProcess()); - - RefPtr content; - content = new ContentParent(this, - MAGIC_PREALLOCATED_APP_MANIFEST_URL, - aPid, - Move(*aFds.get())); - content->Init(); - - size_t numNuwaPrefUpdates = sNuwaPrefUpdates ? - sNuwaPrefUpdates->Length() : 0; - // Resend pref updates to the forked child. - for (size_t i = 0; i < numNuwaPrefUpdates; i++) { - mozilla::Unused << content->SendPreferenceUpdate(sNuwaPrefUpdates->ElementAt(i)); - } - - // Update offline settings. - bool isOffline, isLangRTL, haveBidiKeyboards; - bool isConnected; - InfallibleTArray unusedDictionaries; - ClipboardCapabilities clipboardCaps; - DomainPolicyClone domainPolicy; - StructuredCloneData initialData; - - RecvGetXPCOMProcessAttributes(&isOffline, &isConnected, - &isLangRTL, &haveBidiKeyboards, - &unusedDictionaries, - &clipboardCaps, &domainPolicy, &initialData); - mozilla::Unused << content->SendSetOffline(isOffline); - mozilla::Unused << content->SendSetConnectivity(isConnected); - MOZ_ASSERT(!clipboardCaps.supportsSelectionClipboard() && - !clipboardCaps.supportsFindClipboard(), - "Unexpected values"); - - PreallocatedProcessManager::PublishSpareProcess(content); - return; -#else - NS_ERROR("ContentParent::OnNewProcessCreated() not implemented!"); - return; -#endif -} - // We want ContentParent to show up in CC logs for debugging purposes, but we // don't actually cycle collect it. NS_IMPL_CYCLE_COLLECTION_0(ContentParent) @@ -3057,16 +2746,6 @@ ContentParent::Observe(nsISupports* aSubject, if (!mIsAlive || !mSubprocess) return NS_OK; - // The Nuwa process unregisters the topics after it becomes ready except for - // the ones listed in sNuwaSafeObserverTopics. If the topic needs to be - // observed by the Nuwa process, either for: - // 1. The topic is safe for the Nuwa process, either: - // 1.1 The state can safely happen (only run on the main thread) in the Nuwa - // process (e.g. "a11y-init-or-shutdown"), or - // 1.2 The topic doesn't send an IPC message (e.g. "xpcom-shutdown"). - // 2. The topic needs special handling (e.g. nsPref:Changed), - // add the topic to sNuwaSafeObserverTopics and then handle it if necessary. - // listening for memory pressure event if (!strcmp(aTopic, "memory-pressure") && !StringEndsWith(nsDependentString(aData), @@ -3080,22 +2759,9 @@ ContentParent::Observe(nsISupports* aSubject, PrefSetting pref(strData, null_t(), null_t()); Preferences::GetPreference(&pref); -#ifdef MOZ_NUWA_PROCESS - if (IsReadyNuwaProcess()) { - // Don't send the pref update to the Nuwa process. Save the update - // to send to the forked child. - if (!sNuwaPrefUpdates) { - sNuwaPrefUpdates = new nsTArray(); - } - sNuwaPrefUpdates->AppendElement(pref); - } else if (!SendPreferenceUpdate(pref)) { - return NS_ERROR_NOT_AVAILABLE; - } -#else if (!SendPreferenceUpdate(pref)) { return NS_ERROR_NOT_AVAILABLE; } -#endif } else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) { NS_ConvertUTF16toUTF8 dataStr(aData); @@ -3524,11 +3190,6 @@ void ContentParent::FriendlyName(nsAString& aName, bool aAnonymize) { aName.Truncate(); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - aName.AssignLiteral("(Nuwa)"); - } else -#endif if (IsPreallocated()) { aName.AssignLiteral("(Preallocated)"); } else if (mIsForBrowser) { @@ -4642,10 +4303,6 @@ ContentParent::DoSendAsyncMessage(JSContext* aCx, if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) { return NS_ERROR_UNEXPECTED; } - if (IsReadyNuwaProcess()) { - // Nuwa won't receive frame messages after it is frozen. - return NS_OK; - } if (!SendAsyncMessage(nsString(aMessage), cpows, Principal(aPrincipal), data)) { return NS_ERROR_UNEXPECTED; } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 187e6e576772a..300b6e4390ee5 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -7,7 +7,6 @@ #ifndef mozilla_dom_ContentParent_h #define mozilla_dom_ContentParent_h -#include "mozilla/dom/NuwaParent.h" #include "mozilla/dom/PContentParent.h" #include "mozilla/dom/nsIContentParent.h" #include "mozilla/ipc/GeckoChildProcessHost.h" @@ -101,17 +100,6 @@ class ContentParent final : public PContentParent typedef mozilla::dom::ClonedMessageData ClonedMessageData; public: -#ifdef MOZ_NUWA_PROCESS - static int32_t NuwaPid() - { - return sNuwaPid; - } - - static bool IsNuwaReady() - { - return sNuwaReady; - } -#endif virtual bool IsContentParent() const override { return true; } @@ -151,8 +139,6 @@ class ContentParent final : public PContentParent */ static already_AddRefed PreallocateAppProcess(); - static already_AddRefed RunNuwaProcess(); - /** * Get or create a content process for the given TabContext. aFrameElement * should be the frame/iframe element with which this process will @@ -367,20 +353,6 @@ class ContentParent final : public PContentParent return mIsForBrowser; } -#ifdef MOZ_NUWA_PROCESS - bool IsNuwaProcess() const; -#endif - - // A shorthand for checking if the Nuwa process is ready. - bool IsReadyNuwaProcess() const - { -#ifdef MOZ_NUWA_PROCESS - return IsNuwaProcess() && IsNuwaReady(); -#else - return false; -#endif - } - GeckoChildProcessHost* Process() const { return mSubprocess; @@ -547,8 +519,6 @@ class ContentParent final : public PContentParent virtual bool HandleWindowsMessages(const Message& aMsg) const override; - void SetNuwaParent(NuwaParent* aNuwaParent) { mNuwaParent = aNuwaParent; } - void ForkNewProcess(bool aBlocking); virtual bool RecvCreateWindow(PBrowserParent* aThisTabParent, @@ -596,8 +566,6 @@ class ContentParent final : public PContentParent virtual void ActorDestroy(ActorDestroyReason why) override; - void OnNuwaForkTimeout(); - bool ShouldContinueFromReplyTimeout() override; private: @@ -644,15 +612,7 @@ class ContentParent final : public PContentParent ContentParent(mozIApplication* aApp, ContentParent* aOpener, bool aIsForBrowser, - bool aIsForPreallocated, - bool aIsNuwaProcess = false); - -#ifdef MOZ_NUWA_PROCESS - ContentParent(ContentParent* aTemplate, - const nsAString& aAppManifestURL, - base::ProcessHandle aPid, - InfallibleTArray&& aFds); -#endif + bool aIsForPreallocated); // The common initialization for the constructors. void InitializeMembers(); @@ -1061,11 +1021,6 @@ class ContentParent final : public PContentParent virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable) override; - // Callbacks from NuwaParent. - void OnNuwaReady(); - void OnNewProcessCreated(uint32_t aPid, - UniquePtr>&& aFds); - virtual bool RecvCreateFakeVolume(const nsString& aFsName, const nsString& aMountPoint) override; @@ -1229,7 +1184,6 @@ class ContentParent final : public PContentParent bool mSendPermissionUpdates; bool mIsForBrowser; - bool mIsNuwaProcess; // These variables track whether we've called Close() and KillHard() on our // channel. @@ -1241,9 +1195,6 @@ class ContentParent final : public PContentParent friend class CrashReporterParent; - // Allows NuwaParent to access OnNuwaReady() and OnNewProcessCreated(). - friend class NuwaParent; - RefPtr mConsoleService; nsConsoleService* GetConsoleService(); @@ -1255,17 +1206,8 @@ class ContentParent final : public PContentParent ScopedClose mChildXSocketFdDup; #endif -#ifdef MOZ_NUWA_PROCESS - static int32_t sNuwaPid; - static bool sNuwaReady; -#endif - PProcessHangMonitorParent* mHangMonitorActor; - // NuwaParent and ContentParent hold strong references to each other. The - // cycle will be broken when either actor is destroyed. - RefPtr mNuwaParent; - #ifdef MOZ_ENABLE_PROFILER_SPS RefPtr mGatherer; #endif diff --git a/dom/ipc/NuwaChild.cpp b/dom/ipc/NuwaChild.cpp deleted file mode 100644 index 9b3eca4d2c9fc..0000000000000 --- a/dom/ipc/NuwaChild.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 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 "ContentChild.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif -#include "mozilla/dom/ContentChild.h" -#include "mozilla/ipc/BackgroundChild.h" -#include "mozilla/ipc/PBackgroundChild.h" -#include "mozilla/ipc/ProtocolUtils.h" -#if defined(MOZ_CONTENT_SANDBOX) -#if defined(XP_LINUX) -#include "mozilla/Sandbox.h" -#include "mozilla/SandboxInfo.h" -#elif defined(XP_MACOSX) -#include "mozilla/Sandbox.h" -#endif -#endif -#include "mozilla/unused.h" -#include "nsXULAppAPI.h" -#include "NuwaChild.h" - - -using namespace mozilla::ipc; -using namespace mozilla::dom; - -namespace mozilla { -namespace dom { - -#ifdef MOZ_NUWA_PROCESS - -namespace { - -class CallNuwaSpawn: public Runnable -{ -public: - NS_IMETHOD Run() - { - NuwaSpawn(); - if (IsNuwaProcess()) { - return NS_OK; - } - - // In the new process. - ContentChild* child = ContentChild::GetSingleton(); - child->InitProcessAttributes(); - - // Perform other after-fork initializations. - InitOnContentProcessCreated(); - - return NS_OK; - } -}; - -static void -DoNuwaFork() -{ - NuwaSpawnPrepare(); // NuwaSpawn will be blocked. - - { - nsCOMPtr callSpawn(new CallNuwaSpawn()); - NS_DispatchToMainThread(callSpawn); - } - - // IOThread should be blocked here for waiting NuwaSpawn(). - NuwaSpawnWait(); // Now! NuwaSpawn can go. - // Here, we can make sure the spawning was finished. -} - -/** - * This function should keep IO thread in a stable state and freeze it - * until the spawning is finished. - */ -static void -RunNuwaFork() -{ - if (NuwaCheckpointCurrentThread()) { - DoNuwaFork(); - } -} - -static bool sNuwaForking = false; - -void -NuwaFork() -{ - if (sNuwaForking) { // No reentry. - return; - } - sNuwaForking = true; - - MessageLoop* ioloop = XRE_GetIOMessageLoop(); - ioloop->PostTask(NewRunnableFunction(RunNuwaFork)); -} - -} // Anonymous namespace. - -#endif - -NuwaChild* NuwaChild::sSingleton; - -NuwaChild* -NuwaChild::GetSingleton() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!sSingleton) { - PNuwaChild* nuwaChild = - BackgroundChild::GetForCurrentThread()->SendPNuwaConstructor(); - MOZ_ASSERT(nuwaChild); - - sSingleton = static_cast(nuwaChild); - } - - return sSingleton; -} - - -bool -NuwaChild::RecvFork() -{ -#ifdef MOZ_NUWA_PROCESS - if (!IsNuwaProcess()) { - NS_ERROR( - nsPrintfCString( - "Terminating child process %d for unauthorized IPC message: " - "RecvFork(%d)", getpid()).get()); - return false; - } - - nsCOMPtr runnable = - NS_NewRunnableFunction(&NuwaFork); - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable)); - - return true; -#else - NS_ERROR("NuwaChild::RecvFork() not implemented!"); - return false; -#endif -} - -} // namespace dom -} // namespace mozilla - - -extern "C" { - -#if defined(MOZ_NUWA_PROCESS) -NS_EXPORT void -GetProtoFdInfos(NuwaProtoFdInfo* aInfoList, - size_t aInfoListSize, - size_t* aInfoSize) -{ - size_t i = 0; - - mozilla::dom::ContentChild* content = - mozilla::dom::ContentChild::GetSingleton(); - aInfoList[i].protoId = content->GetProtocolId(); - aInfoList[i].originFd = - content->GetTransport()->GetFileDescriptor(); - i++; - - IToplevelProtocol* actors[NUWA_TOPLEVEL_MAX]; - size_t count = content->GetOpenedActorsUnsafe(actors, ArrayLength(actors)); - for (size_t j = 0; j < count; j++) { - IToplevelProtocol* actor = actors[j]; - if (i >= aInfoListSize) { - NS_RUNTIMEABORT("Too many top level protocols!"); - } - - aInfoList[i].protoId = actor->GetProtocolId(); - aInfoList[i].originFd = - actor->GetTransport()->GetFileDescriptor(); - i++; - } - - if (i > NUWA_TOPLEVEL_MAX) { - NS_RUNTIMEABORT("Too many top level protocols!"); - } - *aInfoSize = i; -} - -class RunAddNewIPCProcess : public mozilla::Runnable -{ -public: - RunAddNewIPCProcess(pid_t aPid, - nsTArray& aMaps) - : mPid(aPid) - { - mMaps.SwapElements(aMaps); - } - - NS_IMETHOD Run() - { - NuwaChild::GetSingleton()->SendAddNewProcess(mPid, mMaps); - - MOZ_ASSERT(sNuwaForking); - sNuwaForking = false; - - return NS_OK; - } - -private: - pid_t mPid; - nsTArray mMaps; -}; - -/** - * AddNewIPCProcess() is called by Nuwa process to tell the parent - * process that a new process is created. - * - * In the newly created process, ResetContentChildTransport() is called to - * reset fd for the IPC Channel and the session. - */ -NS_EXPORT void -AddNewIPCProcess(pid_t aPid, NuwaProtoFdInfo* aInfoList, size_t aInfoListSize) -{ - nsTArray maps; - - for (size_t i = 0; i < aInfoListSize; i++) { - int _fd = aInfoList[i].newFds[NUWA_NEWFD_PARENT]; - mozilla::ipc::FileDescriptor fd(_fd); - mozilla::ipc::ProtocolFdMapping map(aInfoList[i].protoId, fd); - maps.AppendElement(map); - } - - RefPtr runner = new RunAddNewIPCProcess(aPid, maps); - NS_DispatchToMainThread(runner); -} - -NS_EXPORT void -OnNuwaProcessReady() -{ - NuwaChild* nuwaChild = NuwaChild::GetSingleton(); - MOZ_ASSERT(nuwaChild); - - mozilla::Unused << nuwaChild->SendNotifyReady(); -} - -NS_EXPORT void -AfterNuwaFork() -{ - SetCurrentProcessPrivileges(base::PRIVILEGES_DEFAULT); -#if defined(XP_LINUX) && defined(MOZ_SANDBOX) - mozilla::SandboxEarlyInit(XRE_GetProcessType(), /* isNuwa: */ false); -#endif -} - -#endif // MOZ_NUWA_PROCESS - -} diff --git a/dom/ipc/NuwaChild.h b/dom/ipc/NuwaChild.h deleted file mode 100644 index ebde44df6ac1f..0000000000000 --- a/dom/ipc/NuwaChild.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 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 mozilla_dom_NuwaChild_h -#define mozilla_dom_NuwaChild_h - -#include "mozilla/Assertions.h" -#include "mozilla/dom/PNuwaChild.h" -#include "nsThreadUtils.h" - -namespace mozilla { -namespace dom { -class NuwaChild: public mozilla::dom::PNuwaChild -{ -public: - virtual bool RecvFork() override; - - virtual void ActorDestroy(ActorDestroyReason aWhy) override - { } - - static NuwaChild* GetSingleton(); - -private: - static NuwaChild* sSingleton; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_NuwaChild_h diff --git a/dom/ipc/NuwaParent.cpp b/dom/ipc/NuwaParent.cpp deleted file mode 100644 index 48601cd0e83c7..0000000000000 --- a/dom/ipc/NuwaParent.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 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 "mozilla/dom/ContentParent.h" -#include "mozilla/ipc/BackgroundParent.h" -#include "mozilla/ipc/PBackgroundParent.h" -#include "mozilla/unused.h" -#include "nsThreadUtils.h" -#include "NuwaParent.h" - -using namespace mozilla::ipc; -using namespace mozilla::dom; -using namespace IPC; - -namespace mozilla { -namespace dom { - -/*static*/ NuwaParent* -NuwaParent::Alloc() { - RefPtr actor = new NuwaParent(); - return actor.forget().take(); -} - -/*static*/ bool -NuwaParent::ActorConstructed(mozilla::dom::PNuwaParent *aActor) -{ - NuwaParent* actor = static_cast(aActor); - actor->ActorConstructed(); - - return true; -} - -/*static*/ bool -NuwaParent::Dealloc(mozilla::dom::PNuwaParent *aActor) -{ - RefPtr actor = dont_AddRef(static_cast(aActor)); - return true; -} - -NuwaParent::NuwaParent() - : mBlocked(false) - , mMonitor("NuwaParent") - , mClonedActor(nullptr) - , mWorkerThread(do_GetCurrentThread()) - , mNewProcessPid(0) -{ - AssertIsOnBackgroundThread(); -} - -NuwaParent::~NuwaParent() -{ - // Both the worker thread and the main thread (ContentParent) hold a ref to - // this. The instance may be destroyed on either thread. - MOZ_ASSERT(!mContentParent); -} - -inline void -NuwaParent::AssertIsOnWorkerThread() -{ - nsCOMPtr currentThread = do_GetCurrentThread(); - MOZ_ASSERT(currentThread == mWorkerThread); -} - -bool -NuwaParent::ActorConstructed() -{ - AssertIsOnWorkerThread(); - MOZ_ASSERT(Manager()); - MOZ_ASSERT(!mContentParent); - - mContentParent = BackgroundParent::GetContentParent(Manager()); - if (!mContentParent) { - return false; - } - - // mContentParent is guaranteed to be alive. It's safe to set its backward ref - // to this. - mContentParent->SetNuwaParent(this); - return true; -} - -mozilla::ipc::IProtocol* -NuwaParent::CloneProtocol(Channel* aChannel, - ProtocolCloneContext* aCtx) -{ - MOZ_ASSERT(NS_IsMainThread()); - RefPtr self = this; - - MonitorAutoLock lock(mMonitor); - - // Alloc NuwaParent on the worker thread. - nsCOMPtr runnable = NS_NewRunnableFunction([self] () -> void - { - MonitorAutoLock lock(self->mMonitor); - // XXX Calling NuwaParent::Alloc() leads to a compilation error. Use - // self->Alloc() as a workaround. - self->mClonedActor = self->Alloc(); - lock.Notify(); - }); - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS(mWorkerThread->Dispatch(runnable, NS_DISPATCH_NORMAL)); - - while (!mClonedActor) { - lock.Wait(); - } - RefPtr actor = mClonedActor; - mClonedActor = nullptr; - - // mManager of the cloned actor is assigned after returning from this method. - // We can't call ActorConstructed() right after Alloc() in the above runnable. - // To be safe we dispatch a runnable to the current thread to do it. - runnable = NS_NewRunnableFunction([actor] () -> void - { - MOZ_ASSERT(NS_IsMainThread()); - - nsCOMPtr nested = NS_NewRunnableFunction([actor] () -> void - { - AssertIsOnBackgroundThread(); - - // Call NuwaParent::ActorConstructed() on the worker thread. - actor->ActorConstructed(); - - // The actor can finally be deleted after fully constructed. - mozilla::Unused << actor->Send__delete__(actor); - }); - MOZ_ASSERT(nested); - MOZ_ALWAYS_SUCCEEDS(actor->mWorkerThread->Dispatch(nested, NS_DISPATCH_NORMAL)); - }); - - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable)); - - return actor; -} - -void -NuwaParent::ActorDestroy(ActorDestroyReason aWhy) -{ - AssertIsOnWorkerThread(); - - RefPtr self = this; - nsCOMPtr runnable = NS_NewRunnableFunction([self] () -> void - { - // These extra nsRefPtr serve as kungFuDeathGrip to keep both objects from - // deletion in breaking the ref cycle. - RefPtr contentParent = self->mContentParent; - - contentParent->SetNuwaParent(nullptr); - // Need to clear the ref to ContentParent on the main thread. - self->mContentParent = nullptr; - }); - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable)); -} - -bool -NuwaParent::RecvNotifyReady() -{ -#ifdef MOZ_NUWA_PROCESS - if (!mContentParent || !mContentParent->IsNuwaProcess()) { - NS_ERROR("Received NotifyReady() message from a non-Nuwa process."); - return false; - } - - // Creating a NonOwningRunnableMethod here is safe because refcount changes of - // mContentParent have to go the the main thread. The mContentParent will - // be alive when the runnable runs. - nsCOMPtr runnable = - NewNonOwningRunnableMethod(mContentParent.get(), - &ContentParent::OnNuwaReady); - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable)); - - return true; -#else - NS_ERROR("NuwaParent::RecvNotifyReady() not implemented!"); - return false; -#endif -} - -bool -NuwaParent::RecvAddNewProcess(const uint32_t& aPid, - nsTArray&& aFds) -{ -#ifdef MOZ_NUWA_PROCESS - if (!mContentParent || !mContentParent->IsNuwaProcess()) { - NS_ERROR("Received AddNewProcess() message from a non-Nuwa process."); - return false; - } - - mNewProcessPid = aPid; - mNewProcessFds->SwapElements(aFds); - MonitorAutoLock lock(mMonitor); - if (mBlocked) { - // Unblock ForkNewProcess(). - mMonitor.Notify(); - mBlocked = false; - } else { - nsCOMPtr runnable = - NewNonOwningRunnableMethod< - uint32_t, - UniquePtr>&& >( - mContentParent.get(), - &ContentParent::OnNewProcessCreated, - mNewProcessPid, - Move(mNewProcessFds)); - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable)); - } - return true; -#else - NS_ERROR("NuwaParent::RecvAddNewProcess() not implemented!"); - return false; -#endif -} - -bool -NuwaParent::ForkNewProcess(uint32_t& aPid, - UniquePtr>&& aFds, - bool aBlocking) -{ - MOZ_ASSERT(mWorkerThread); - MOZ_ASSERT(NS_IsMainThread()); - - mNewProcessFds = Move(aFds); - - RefPtr self = this; - nsCOMPtr runnable = NS_NewRunnableFunction([self] () -> void - { - mozilla::Unused << self->SendFork(); - }); - MOZ_ASSERT(runnable); - MOZ_ALWAYS_SUCCEEDS(mWorkerThread->Dispatch(runnable, NS_DISPATCH_NORMAL)); - if (!aBlocking) { - return false; - } - - MonitorAutoLock lock(mMonitor); - mBlocked = true; - while (mBlocked) { - // This will be notified in NuwaParent::RecvAddNewProcess(). - lock.Wait(); - } - - if (!mNewProcessPid) { - return false; - } - - aPid = mNewProcessPid; - aFds = Move(mNewProcessFds); - - mNewProcessPid = 0; - return true; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/ipc/NuwaParent.h b/dom/ipc/NuwaParent.h deleted file mode 100644 index 06985386acc31..0000000000000 --- a/dom/ipc/NuwaParent.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 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 mozilla_dom_NuwaParent_h -#define mozilla_dom_NuwaParent_h - -#include "base/message_loop.h" -#include "mozilla/dom/PNuwaParent.h" -#include "mozilla/Monitor.h" -#include "mozilla/RefPtr.h" - -namespace mozilla { -namespace dom { - -class ContentParent; - -class NuwaParent : public mozilla::dom::PNuwaParent -{ -public: - explicit NuwaParent(); - - // Called on the main thread. - bool ForkNewProcess(uint32_t& aPid, - UniquePtr>&& aFds, - bool aBlocking); - - // Called on the background thread. - bool ActorConstructed(); - - // Both the worker thread and the main thread hold a ref to this. - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NuwaParent) - - // Functions to be invoked by the manager of this actor to alloc/dealloc the - // actor. - static NuwaParent* Alloc(); - static bool ActorConstructed(mozilla::dom::PNuwaParent *aActor); - static bool Dealloc(mozilla::dom::PNuwaParent *aActor); - -protected: - virtual ~NuwaParent(); - - virtual bool RecvNotifyReady() override; - virtual bool RecvAddNewProcess(const uint32_t& aPid, - nsTArray&& aFds) override; - virtual mozilla::ipc::IProtocol* - CloneProtocol(Channel* aChannel, - ProtocolCloneContext* aCtx) override; - - virtual void ActorDestroy(ActorDestroyReason aWhy) override; - -private: - void AssertIsOnWorkerThread(); - - bool mBlocked; - mozilla::Monitor mMonitor; - NuwaParent* mClonedActor; - - nsCOMPtr mWorkerThread; - - uint32_t mNewProcessPid; - UniquePtr> mNewProcessFds; - - // The mutual reference will be broken on the main thread. - RefPtr mContentParent; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_NuwaParent_h diff --git a/dom/ipc/PNuwa.ipdl b/dom/ipc/PNuwa.ipdl deleted file mode 100644 index 8da39194d4c03..0000000000000 --- a/dom/ipc/PNuwa.ipdl +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 protocol PBackground; -include ProtocolTypes; - -namespace mozilla { -namespace dom { - -sync protocol PNuwa -{ - manager PBackground; - -child: - // Ask the Nuwa process to create a new child process. - async Fork(); - - // This message will be sent to non-Nuwa process, or to Nuwa process during - // test. - async __delete__(); - -parent: - async NotifyReady(); - sync AddNewProcess(uint32_t pid, ProtocolFdMapping[] aFds); -}; - -} // namespace layout -} // namespace mozilla - diff --git a/dom/ipc/PreallocatedProcessManager.cpp b/dom/ipc/PreallocatedProcessManager.cpp index 296d7d1510f9a..c7d9ebc98e19a 100644 --- a/dom/ipc/PreallocatedProcessManager.cpp +++ b/dom/ipc/PreallocatedProcessManager.cpp @@ -14,19 +14,10 @@ #include "ProcessPriorityManager.h" #include "nsServiceManagerUtils.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - -#ifdef MOZ_B2G_LOADER -#include "ProcessUtils.h" -#endif - // This number is fairly arbitrary ... the intention is to put off // launching another app process until the last one has finished // loading its content, to reduce CPU/memory/IO contention. #define DEFAULT_ALLOCATE_DELAY 1000 -#define NUWA_FORK_WAIT_DURATION_MS 2000 // 2 seconds. using namespace mozilla; using namespace mozilla::hal; @@ -53,31 +44,6 @@ class PreallocatedProcessManagerImpl final void AllocateNow(); already_AddRefed Take(); -#ifdef MOZ_NUWA_PROCESS -public: - void ScheduleDelayedNuwaFork(); - void DelayedNuwaFork(); - void PublishSpareProcess(ContentParent* aContent); - void MaybeForgetSpare(ContentParent* aContent); - bool IsNuwaReady(); - void OnNuwaReady(); - bool PreallocatedProcessReady(); - already_AddRefed GetSpareProcess(); - -private: - void NuwaFork(); - - // initialization off the critical path of app startup. - CancelableRunnable* mPreallocateAppProcessTask; - - // The array containing the preallocated processes. 4 as the inline storage size - // should be enough so we don't need to grow the AutoTArray. - AutoTArray, 4> mSpareProcesses; - - // Nuwa process is ready for creating new process. - bool mIsNuwaReady; -#endif - private: static mozilla::StaticRefPtr sSingleton; @@ -117,11 +83,6 @@ NS_IMPL_ISUPPORTS(PreallocatedProcessManagerImpl, nsIObserver) PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl() : -#ifdef MOZ_NUWA_PROCESS - mPreallocateAppProcessTask(nullptr) - , mIsNuwaReady(false) - , -#endif mEnabled(false) , mShutdown(false) {} @@ -137,11 +98,6 @@ PreallocatedProcessManagerImpl::Init() os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, /* weakRef = */ false); } -#ifdef MOZ_B2G_LOADER - if (!mozilla::ipc::ProcLoaderIsInitialized()) { - Disable(); - } else -#endif { RereadPrefs(); } @@ -190,11 +146,7 @@ PreallocatedProcessManagerImpl::Enable() } mEnabled = true; -#ifdef MOZ_NUWA_PROCESS - ScheduleDelayedNuwaFork(); -#else AllocateAfterDelay(); -#endif } void @@ -230,174 +182,6 @@ PreallocatedProcessManagerImpl::AllocateNow() mPreallocatedAppProcess = ContentParent::PreallocateAppProcess(); } -#ifdef MOZ_NUWA_PROCESS - -void -PreallocatedProcessManagerImpl::ScheduleDelayedNuwaFork() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (mPreallocateAppProcessTask) { - // Make sure there is only one request running. - return; - } - - RefPtr task = NewCancelableRunnableMethod( - this, &PreallocatedProcessManagerImpl::DelayedNuwaFork); - mPreallocateAppProcessTask = task; - MessageLoop::current()->PostDelayedTask(task.forget(), - Preferences::GetUint("dom.ipc.processPrelaunch.delayMs", - DEFAULT_ALLOCATE_DELAY)); -} - -void -PreallocatedProcessManagerImpl::DelayedNuwaFork() -{ - MOZ_ASSERT(NS_IsMainThread()); - - mPreallocateAppProcessTask = nullptr; - - if (!mIsNuwaReady) { - if (!mPreallocatedAppProcess && !mShutdown && mEnabled) { - mPreallocatedAppProcess = ContentParent::RunNuwaProcess(); - } - // else mPreallocatedAppProcess is starting. It will NuwaFork() when ready. - } else if (mSpareProcesses.IsEmpty()) { - NuwaFork(); - } -} - -/** - * Get a spare ContentParent from mSpareProcesses list. - */ -already_AddRefed -PreallocatedProcessManagerImpl::GetSpareProcess() -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (!mIsNuwaReady) { - return nullptr; - } - - if (mSpareProcesses.IsEmpty()) { - // After this call, there should be a spare process. - mPreallocatedAppProcess->ForkNewProcess(true); - } - - RefPtr process = mSpareProcesses.LastElement(); - mSpareProcesses.RemoveElementAt(mSpareProcesses.Length() - 1); - - if (mSpareProcesses.IsEmpty() && mIsNuwaReady) { - NS_ASSERTION(mPreallocatedAppProcess != nullptr, - "Nuwa process is not present!"); - ScheduleDelayedNuwaFork(); - } - - return process.forget(); -} - -static bool -TestCaseEnabled() -{ - return Preferences::GetBool("dom.ipc.preallocatedProcessManager.testMode"); -} - -static void -SendTestOnlyNotification(const char* aMessage) -{ - if (!TestCaseEnabled()) { - return; - } - - AutoSafeJSContext cx; - nsString message; - message.AppendPrintf("%s", aMessage); - - nsCOMPtr ppmm = - do_GetService("@mozilla.org/parentprocessmessagemanager;1"); - - mozilla::Unused << ppmm->BroadcastAsyncMessage( - message, JS::NullHandleValue, JS::NullHandleValue, cx, 1); -} - -static void -KillOrCloseProcess(ContentParent* aProcess) -{ - if (TestCaseEnabled()) { - // KillHard() the process because we don't want the process to abort when we - // close the IPC channel while it's still running and creating actors. - aProcess->KillHard("Killed by test case."); - } - else { - aProcess->Close(); - } -} - -/** - * Publish a ContentParent to spare process list. - */ -void -PreallocatedProcessManagerImpl::PublishSpareProcess(ContentParent* aContent) -{ - MOZ_ASSERT(NS_IsMainThread()); - - SendTestOnlyNotification("TEST-ONLY:nuwa-add-new-process"); - - mSpareProcesses.AppendElement(aContent); -} - -void -PreallocatedProcessManagerImpl::MaybeForgetSpare(ContentParent* aContent) -{ - MOZ_ASSERT(NS_IsMainThread()); - - if (mSpareProcesses.RemoveElement(aContent)) { - return; - } - - if (aContent == mPreallocatedAppProcess) { - mPreallocatedAppProcess = nullptr; - mIsNuwaReady = false; - while (mSpareProcesses.Length() > 0) { - RefPtr process = mSpareProcesses[mSpareProcesses.Length() - 1]; - KillOrCloseProcess(aContent); - mSpareProcesses.RemoveElementAt(mSpareProcesses.Length() - 1); - } - ScheduleDelayedNuwaFork(); - } -} - -bool -PreallocatedProcessManagerImpl::IsNuwaReady() -{ - return mIsNuwaReady; -} - -void -PreallocatedProcessManagerImpl::OnNuwaReady() -{ - NS_ASSERTION(!mIsNuwaReady, "Multiple Nuwa processes created!"); - ProcessPriorityManager::SetProcessPriority(mPreallocatedAppProcess, - hal::PROCESS_PRIORITY_MASTER); - mIsNuwaReady = true; - SendTestOnlyNotification("TEST-ONLY:nuwa-ready"); - - NuwaFork(); -} - -bool -PreallocatedProcessManagerImpl::PreallocatedProcessReady() -{ - return !mSpareProcesses.IsEmpty(); -} - -void -PreallocatedProcessManagerImpl::NuwaFork() -{ - mPreallocatedAppProcess->ForkNewProcess(false); -} -#endif - void PreallocatedProcessManagerImpl::Disable() { @@ -407,23 +191,7 @@ PreallocatedProcessManagerImpl::Disable() mEnabled = false; -#ifdef MOZ_NUWA_PROCESS - // Cancel pending fork. - if (mPreallocateAppProcessTask) { - mPreallocateAppProcessTask->Cancel(); - mPreallocateAppProcessTask = nullptr; - } -#endif - if (mPreallocatedAppProcess) { -#ifdef MOZ_NUWA_PROCESS - while (mSpareProcesses.Length() > 0){ - RefPtr process = mSpareProcesses[0]; - KillOrCloseProcess(process); - mSpareProcesses.RemoveElementAt(0); - } - mIsNuwaReady = false; -#endif mPreallocatedAppProcess->Close(); mPreallocatedAppProcess = nullptr; } @@ -460,11 +228,7 @@ namespace mozilla { /* static */ void PreallocatedProcessManager::AllocateAfterDelay() { -#ifdef MOZ_NUWA_PROCESS - GetPPMImpl()->ScheduleDelayedNuwaFork(); -#else GetPPMImpl()->AllocateAfterDelay(); -#endif } /* static */ void @@ -482,44 +246,7 @@ PreallocatedProcessManager::AllocateNow() /* static */ already_AddRefed PreallocatedProcessManager::Take() { -#ifdef MOZ_NUWA_PROCESS - return GetPPMImpl()->GetSpareProcess(); -#else return GetPPMImpl()->Take(); -#endif -} - -#ifdef MOZ_NUWA_PROCESS -/* static */ void -PreallocatedProcessManager::PublishSpareProcess(ContentParent* aContent) -{ - GetPPMImpl()->PublishSpareProcess(aContent); -} - -/* static */ void -PreallocatedProcessManager::MaybeForgetSpare(ContentParent* aContent) -{ - GetPPMImpl()->MaybeForgetSpare(aContent); -} - -/* static */ void -PreallocatedProcessManager::OnNuwaReady() -{ - GetPPMImpl()->OnNuwaReady(); } -/* static */ bool -PreallocatedProcessManager::IsNuwaReady() -{ - return GetPPMImpl()->IsNuwaReady(); -} - -/*static */ bool -PreallocatedProcessManager::PreallocatedProcessReady() -{ - return GetPPMImpl()->PreallocatedProcessReady(); -} - -#endif - } // namespace mozilla diff --git a/dom/ipc/PreallocatedProcessManager.h b/dom/ipc/PreallocatedProcessManager.h index 298390dc962aa..94acd31fd7abe 100644 --- a/dom/ipc/PreallocatedProcessManager.h +++ b/dom/ipc/PreallocatedProcessManager.h @@ -78,14 +78,6 @@ class PreallocatedProcessManager final */ static already_AddRefed Take(); -#ifdef MOZ_NUWA_PROCESS - static void PublishSpareProcess(ContentParent* aContent); - static void MaybeForgetSpare(ContentParent* aContent); - static bool IsNuwaReady(); - static void OnNuwaReady(); - static bool PreallocatedProcessReady(); -#endif - private: PreallocatedProcessManager(); DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager); diff --git a/dom/ipc/ProcessPriorityManager.cpp b/dom/ipc/ProcessPriorityManager.cpp index 853f6de954cd1..cebc09598a0e7 100644 --- a/dom/ipc/ProcessPriorityManager.cpp +++ b/dom/ipc/ProcessPriorityManager.cpp @@ -526,13 +526,6 @@ already_AddRefed ProcessPriorityManagerImpl::GetParticularProcessPriorityManager( ContentParent* aContentParent) { -#ifdef MOZ_NUWA_PROCESS - // Do not attempt to change the priority of the Nuwa process - if (aContentParent->IsNuwaProcess()) { - return nullptr; - } -#endif - RefPtr pppm; uint64_t cpId = aContentParent->ChildID(); mParticularManagers.Get(cpId, &pppm); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 573b61619cd83..e8ec14d87561b 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -24,9 +24,6 @@ #include "mozilla/IMEStateManager.h" #include "mozilla/ipc/DocumentRendererChild.h" #include "mozilla/ipc/URIUtils.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif #include "mozilla/ipc/FileDescriptorUtils.h" #include "mozilla/layers/APZChild.h" #include "mozilla/layers/APZCCallbackHelper.h" @@ -456,41 +453,6 @@ PreloadSlowThingsPostFork(void* aUnused) } -#ifdef MOZ_NUWA_PROCESS -class MessageChannelAutoBlock MOZ_STACK_CLASS -{ -public: - MessageChannelAutoBlock() - { - SetMessageChannelBlocked(true); - } - - ~MessageChannelAutoBlock() - { - SetMessageChannelBlocked(false); - } - -private: - void SetMessageChannelBlocked(bool aBlock) - { - if (!IsNuwaProcess()) { - return; - } - - mozilla::dom::ContentChild* content = - mozilla::dom::ContentChild::GetSingleton(); - if (aBlock) { - content->GetIPCChannel()->Block(); - } else { - content->GetIPCChannel()->Unblock(); - } - - // Other IPC channels do not perform the checks through Block() and - // Unblock(). - } -}; -#endif - static bool sPreloaded = false; /*static*/ void @@ -513,12 +475,6 @@ TabChild::PreloadSlowThings() return; } -#ifdef MOZ_NUWA_PROCESS - // Temporarily block the IPC channels to the chrome process when we are - // preloading. - MessageChannelAutoBlock autoblock; -#endif - // Just load and compile these scripts, but don't run them. tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true); // Load, compile, and run these scripts. @@ -529,15 +485,7 @@ TabChild::PreloadSlowThings() sPreallocatedTab = tab; ClearOnShutdown(&sPreallocatedTab); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaAddFinalConstructor(PreloadSlowThingsPostFork, nullptr); - } else { - PreloadSlowThingsPostFork(nullptr); - } -#else PreloadSlowThingsPostFork(nullptr); -#endif } /*static*/ already_AddRefed diff --git a/dom/ipc/TabContext.h b/dom/ipc/TabContext.h index c853530c3f653..06604646111e3 100644 --- a/dom/ipc/TabContext.h +++ b/dom/ipc/TabContext.h @@ -10,6 +10,7 @@ #include "mozIApplication.h" #include "nsCOMPtr.h" #include "mozilla/BasePrincipal.h" +#include "nsPIDOMWindow.h" #include "nsPIWindowRoot.h" namespace mozilla { diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 836bd70a8aecd..ad6a8318922e3 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -61,6 +61,7 @@ #include "nsPrincipal.h" #include "nsIPromptFactory.h" #include "nsIURI.h" +#include "nsIWindowWatcher.h" #include "nsIWebBrowserChrome.h" #include "nsIXULBrowserWindow.h" #include "nsIXULWindow.h" @@ -108,6 +109,8 @@ using namespace mozilla::widget; using namespace mozilla::jsipc; using namespace mozilla::gfx; +using mozilla::Unused; + // The flags passed by the webProgress notifications are 16 bits shifted // from the ones registered by webProgressListeners. #define NOTIFY_FLAG_SHIFT 16 diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index 8b8eba5eb7c96..23e7be610b0f7 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -35,8 +35,6 @@ EXPORTS.mozilla.dom += [ 'FilePickerParent.h', 'nsIContentChild.h', 'nsIContentParent.h', - 'NuwaChild.h', - 'NuwaParent.h', 'PermissionMessageUtils.h', 'TabChild.h', 'TabContext.h', @@ -65,8 +63,6 @@ UNIFIED_SOURCES += [ 'FilePickerParent.cpp', 'nsIContentChild.cpp', 'nsIContentParent.cpp', - 'NuwaChild.cpp', - 'NuwaParent.cpp', 'PermissionMessageUtils.cpp', 'PreallocatedProcessManager.cpp', 'ProcessPriorityManager.cpp', @@ -107,7 +103,6 @@ IPDL_SOURCES += [ 'PDocumentRenderer.ipdl', 'PFilePicker.ipdl', 'PMemoryReportRequest.ipdl', - 'PNuwa.ipdl', 'PPluginWidget.ipdl', 'PProcessHangMonitor.ipdl', 'PScreenManager.ipdl', diff --git a/dom/ipc/tests/mochitest.ini b/dom/ipc/tests/mochitest.ini index 6d96800297bec..8032f4414605f 100644 --- a/dom/ipc/tests/mochitest.ini +++ b/dom/ipc/tests/mochitest.ini @@ -13,10 +13,6 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s skip-if = buildapp == 'b2g' || e10s || toolkit == 'android' [test_cpow_cookies.html] skip-if = buildapp == 'b2g' || buildapp == 'mulet' -[test_NuwaProcessCreation.html] -skip-if = toolkit != 'gonk' -[test_NuwaProcessDeadlock.html] -skip-if = toolkit != 'gonk' [test_child_docshell.html] skip-if = toolkit == 'cocoa' # disabled due to hangs, see changeset 6852e7c47edf [test_CrashService_crash.html] diff --git a/dom/ipc/tests/test_NuwaProcessCreation.html b/dom/ipc/tests/test_NuwaProcessCreation.html deleted file mode 100644 index baede677f365b..0000000000000 --- a/dom/ipc/tests/test_NuwaProcessCreation.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/ipc/tests/test_NuwaProcessDeadlock.html b/dom/ipc/tests/test_NuwaProcessDeadlock.html deleted file mode 100644 index 150707f5b3b5e..0000000000000 --- a/dom/ipc/tests/test_NuwaProcessDeadlock.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - diff --git a/dom/storage/DOMStorageIPC.cpp b/dom/storage/DOMStorageIPC.cpp index 81b4bafdbbac4..c961f7de6e55b 100644 --- a/dom/storage/DOMStorageIPC.cpp +++ b/dom/storage/DOMStorageIPC.cpp @@ -615,16 +615,9 @@ DOMStorageDBParent::Observe(const char* aTopic, const nsACString& aOriginScope) { if (mIPCOpen) { -#ifdef MOZ_NUWA_PROCESS - if (!(static_cast(Manager())->IsNuwaProcess() && - ContentParent::IsNuwaReady())) { -#endif mozilla::Unused << SendObserve(nsDependentCString(aTopic), nsString(aOriginAttributesPattern), nsCString(aOriginScope)); -#ifdef MOZ_NUWA_PROCESS - } -#endif } return NS_OK; diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index b6b03c2ee8e6d..079c22146c569 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -59,10 +59,6 @@ #include "OSFileConstants.h" #include "xpcpublic.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - #include "Principal.h" #include "SharedWorker.h" #include "WorkerDebuggerManager.h" @@ -2494,13 +2490,6 @@ WorkerThreadPrimaryRunnable::Run() { using mozilla::ipc::BackgroundChild; -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - NuwaFreezeCurrentThread(); - } -#endif - char stackBaseGuess; PR_SetCurrentThreadName("DOM Worker"); diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index 6b04e70880fc2..ec46e2d537f41 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -564,10 +564,6 @@ bool ImageBridgeChild::IsCreated() return GetSingleton() != nullptr; } -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - static void ReleaseImageClientNow(ImageClient* aClient, PImageContainerChild* aChild) { diff --git a/gfx/layers/ipc/SharedBufferManagerChild.cpp b/gfx/layers/ipc/SharedBufferManagerChild.cpp index 2dd3124200a51..fb443b34dcec1 100644 --- a/gfx/layers/ipc/SharedBufferManagerChild.cpp +++ b/gfx/layers/ipc/SharedBufferManagerChild.cpp @@ -14,10 +14,6 @@ #include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc #include "nsThreadUtils.h" // fo NS_IsMainThread -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - #ifdef MOZ_WIDGET_GONK #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "SBMChild", ## args) #endif @@ -103,14 +99,6 @@ ConnectSharedBufferManagerInChildProcess(mozilla::ipc::Transport* aTransport, XRE_GetIOMessageLoop(), ipc::ChildSide); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - SharedBufferManagerChild::sSharedBufferManagerChildThread - ->message_loop()->PostTask(NewRunnableFunction(NuwaMarkCurrentThread, - (void (*)(void *))nullptr, - (void *)nullptr)); - } -#endif } PSharedBufferManagerChild* diff --git a/image/DecodePool.cpp b/image/DecodePool.cpp index c2bce0e0d35c3..a609841ab3320 100644 --- a/image/DecodePool.cpp +++ b/image/DecodePool.cpp @@ -17,10 +17,6 @@ #include "nsXPCOMCIDInternal.h" #include "prsystem.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - #include "gfxPrefs.h" #include "Decoder.h" @@ -69,12 +65,6 @@ class DecodePoolImpl MOZ_ASSERT(!NS_IsMainThread()); mThreadNaming.SetThreadPoolName(NS_LITERAL_CSTRING("ImgDecoder")); - -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(static_cast(nullptr), nullptr); - } -#endif // MOZ_NUWA_PROCESS } /// Shut down the provided decode pool thread. @@ -271,15 +261,6 @@ DecodePool::DecodePool() MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv) && mIOThread, "Should successfully create image I/O thread"); -#ifdef MOZ_NUWA_PROCESS - rv = mIOThread->Dispatch(NS_NewRunnableFunction([]() -> void { - NuwaMarkCurrentThread(static_cast(nullptr), nullptr); - }), NS_DISPATCH_NORMAL); - - MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv), - "Should register decode IO thread with Nuwa process"); -#endif - nsCOMPtr obsSvc = services::GetObserverService(); if (obsSvc) { obsSvc->AddObserver(this, "xpcom-shutdown-threads", false); diff --git a/ipc/chromium/src/base/process_util_linux.cc b/ipc/chromium/src/base/process_util_linux.cc index 407ece91433e0..204017db505c8 100644 --- a/ipc/chromium/src/base/process_util_linux.cc +++ b/ipc/chromium/src/base/process_util_linux.cc @@ -24,12 +24,6 @@ #include "prenv.h" #include "prmem.h" -#ifdef MOZ_B2G_LOADER -#include "ProcessUtils.h" - -using namespace mozilla::ipc; -#endif // MOZ_B2G_LOADER - #ifdef MOZ_WIDGET_GONK /* * AID_APP is the first application UID used by Android. We're using @@ -160,71 +154,12 @@ bool LaunchApp(const std::vector& argv, wait, process_handle); } -#ifdef MOZ_B2G_LOADER -/** - * Launch an app using B2g Loader. - */ -static bool -LaunchAppProcLoader(const std::vector& argv, - const file_handle_mapping_vector& fds_to_remap, - const environment_map& env_vars_to_set, - ChildPrivileges privs, - ProcessHandle* process_handle) { - size_t i; - mozilla::UniquePtr argv_cstr(new char*[argv.size() + 1]); - for (i = 0; i < argv.size(); i++) { - argv_cstr[i] = const_cast(argv[i].c_str()); - } - argv_cstr[argv.size()] = nullptr; - - mozilla::UniquePtr env_cstr(new char*[env_vars_to_set.size() + 1]); - i = 0; - for (environment_map::const_iterator it = env_vars_to_set.begin(); - it != env_vars_to_set.end(); ++it) { - env_cstr[i++] = strdup((it->first + "=" + it->second).c_str()); - } - env_cstr[env_vars_to_set.size()] = nullptr; - - bool ok = ProcLoaderLoad((const char **)argv_cstr.get(), - (const char **)env_cstr.get(), - fds_to_remap, privs, - process_handle); - MOZ_ASSERT(ok, "ProcLoaderLoad() failed"); - - for (size_t i = 0; i < env_vars_to_set.size(); i++) { - free(env_cstr[i]); - } - - return ok; -} - -static bool -IsLaunchingNuwa(const std::vector& argv) { - std::vector::const_iterator it; - for (it = argv.begin(); it != argv.end(); ++it) { - if (*it == std::string("-nuwa")) { - return true; - } - } - return false; -} -#endif // MOZ_B2G_LOADER - bool LaunchApp(const std::vector& argv, const file_handle_mapping_vector& fds_to_remap, const environment_map& env_vars_to_set, ChildPrivileges privs, bool wait, ProcessHandle* process_handle, ProcessArchitecture arch) { -#ifdef MOZ_B2G_LOADER - static bool beforeFirstNuwaLaunch = true; - if (!wait && beforeFirstNuwaLaunch && IsLaunchingNuwa(argv)) { - beforeFirstNuwaLaunch = false; - return LaunchAppProcLoader(argv, fds_to_remap, env_vars_to_set, - privs, process_handle); - } -#endif // MOZ_B2G_LOADER - mozilla::UniquePtr argv_cstr(new char*[argv.size() + 1]); // Illegal to allocate memory after fork and before execvp InjectiveMultimap fd_shuffle1, fd_shuffle2; diff --git a/ipc/chromium/src/chrome/common/child_thread.cc b/ipc/chromium/src/chrome/common/child_thread.cc index 22d3ba52ea3ac..619f73c5d4d13 100644 --- a/ipc/chromium/src/chrome/common/child_thread.cc +++ b/ipc/chromium/src/chrome/common/child_thread.cc @@ -23,17 +23,8 @@ ChildThread::ChildThread(Thread::Options options) ChildThread::~ChildThread() { } -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - bool ChildThread::Run() { bool r = StartWithOptions(options_); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - message_loop()->PostTask(NewRunnableFunction(&ChildThread::MarkThread)); - } -#endif return r; } @@ -42,15 +33,6 @@ void ChildThread::OnChannelError() { owner_loop_->PostTask(task.forget()); } -#ifdef MOZ_NUWA_PROCESS -void ChildThread::MarkThread() { - NuwaMarkCurrentThread(nullptr, nullptr); - if (!NuwaCheckpointCurrentThread()) { - NS_RUNTIMEABORT("Should not be here!"); - } -} -#endif - void ChildThread::OnMessageReceived(IPC::Message&& msg) { } diff --git a/ipc/chromium/src/chrome/common/child_thread.h b/ipc/chromium/src/chrome/common/child_thread.h index 32f3b5d397820..a36d16ec9c832 100644 --- a/ipc/chromium/src/chrome/common/child_thread.h +++ b/ipc/chromium/src/chrome/common/child_thread.h @@ -42,10 +42,6 @@ class ChildThread : public IPC::Channel::Listener, virtual void OnMessageReceived(IPC::Message&& msg); virtual void OnChannelError(); -#ifdef MOZ_NUWA_PROCESS - static void MarkThread(); -#endif - // The message loop used to run tasks on the thread that started this thread. MessageLoop* owner_loop_; diff --git a/ipc/contentproc/moz.build b/ipc/contentproc/moz.build index 765b219940b82..07cf0b97c6767 100644 --- a/ipc/contentproc/moz.build +++ b/ipc/contentproc/moz.build @@ -5,8 +5,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. Library('plugin-container') -if CONFIG['MOZ_B2G_LOADER']: - FINAL_LIBRARY = 'xul' SOURCES += [ 'plugin-container.cpp', diff --git a/ipc/contentproc/plugin-container.cpp b/ipc/contentproc/plugin-container.cpp index 7356c11fe460a..f293889b0a52a 100644 --- a/ipc/contentproc/plugin-container.cpp +++ b/ipc/contentproc/plugin-container.cpp @@ -55,11 +55,6 @@ #endif // MOZ_WIDGET_GONK -#ifdef MOZ_NUWA_PROCESS -#include -#include "ipc/Nuwa.h" -#endif - #ifdef MOZ_WIDGET_GONK static void InitializeBinder(void *aDummy) { @@ -150,11 +145,6 @@ content_process_main(int argc, char* argv[]) return 3; } - bool isNuwa = false; - for (int i = 1; i < argc; i++) { - isNuwa |= strcmp(argv[i], "-nuwa") == 0; - } - XREChildData childData; #if defined(XP_WIN) && defined(MOZ_SANDBOX) @@ -171,20 +161,11 @@ content_process_main(int argc, char* argv[]) XRE_SetProcessType(argv[--argc]); -#ifdef MOZ_NUWA_PROCESS - if (isNuwa) { - PrepareNuwaProcess(); - } -#endif - #if defined(XP_LINUX) && defined(MOZ_SANDBOX) // This has to happen while we're still single-threaded, and on // B2G that means before the Android Binder library is - // initialized. Additional special handling is needed for Nuwa: - // the Nuwa process itself needs to be unsandboxed, and the same - // single-threadedness condition applies to its children; see also - // AfterNuwaFork(). - mozilla::SandboxEarlyInit(XRE_GetProcessType(), isNuwa); + // initialized. + mozilla::SandboxEarlyInit(XRE_GetProcessType()); #endif #ifdef MOZ_WIDGET_GONK @@ -193,16 +174,8 @@ content_process_main(int argc, char* argv[]) // ProcessState::Self() also needs to be called once on the main thread to // register the main thread with the binder driver. -#ifdef MOZ_NUWA_PROCESS - if (!isNuwa) { - InitializeBinder(nullptr); - } else { - NuwaAddFinalConstructor(&InitializeBinder, nullptr); - } -#else InitializeBinder(nullptr); #endif -#endif #ifdef XP_WIN // For plugins, this is done in PluginProcessChild::Init, as we need to diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp index 21c034a1cf2ec..27a90479bd2b5 100644 --- a/ipc/glue/BackgroundChildImpl.cpp +++ b/ipc/glue/BackgroundChildImpl.cpp @@ -29,7 +29,6 @@ #include "mozilla/dom/GamepadTestChannelChild.h" #endif #include "mozilla/dom/MessagePortChild.h" -#include "mozilla/dom/NuwaChild.h" #include "mozilla/ipc/PBackgroundTestChild.h" #include "mozilla/ipc/PSendStreamChild.h" #include "mozilla/layout/VsyncChild.h" @@ -75,7 +74,6 @@ using mozilla::dom::asmjscache::PAsmJSCacheEntryChild; using mozilla::dom::cache::PCacheChild; using mozilla::dom::cache::PCacheStorageChild; using mozilla::dom::cache::PCacheStreamControlChild; -using mozilla::dom::PNuwaChild; // ----------------------------------------------------------------------------- // BackgroundChildImpl::ThreadLocal @@ -409,21 +407,6 @@ BackgroundChildImpl::DeallocPMessagePortChild(PMessagePortChild* aActor) return true; } -PNuwaChild* -BackgroundChildImpl::AllocPNuwaChild() -{ - return new mozilla::dom::NuwaChild(); -} - -bool -BackgroundChildImpl::DeallocPNuwaChild(PNuwaChild* aActor) -{ - MOZ_ASSERT(aActor); - - delete aActor; - return true; -} - PSendStreamChild* BackgroundChildImpl::AllocPSendStreamChild() { diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h index 0c5702752d357..f8c2a5576b974 100644 --- a/ipc/glue/BackgroundChildImpl.h +++ b/ipc/glue/BackgroundChildImpl.h @@ -140,12 +140,6 @@ class BackgroundChildImpl : public PBackgroundChild virtual bool DeallocPMessagePortChild(PMessagePortChild* aActor) override; - virtual PNuwaChild* - AllocPNuwaChild() override; - - virtual bool - DeallocPNuwaChild(PNuwaChild* aActor) override; - virtual PSendStreamChild* AllocPSendStreamChild() override; diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp index 1458f2dc9acbd..ffb44f05433db 100644 --- a/ipc/glue/BackgroundParentImpl.cpp +++ b/ipc/glue/BackgroundParentImpl.cpp @@ -22,7 +22,6 @@ #include "mozilla/dom/GamepadEventChannelParent.h" #include "mozilla/dom/GamepadTestChannelParent.h" #endif -#include "mozilla/dom/NuwaParent.h" #include "mozilla/dom/PBlobParent.h" #include "mozilla/dom/PGamepadEventChannelParent.h" #include "mozilla/dom/PGamepadTestChannelParent.h" @@ -66,9 +65,7 @@ using mozilla::dom::cache::PCacheStreamControlParent; using mozilla::dom::FileSystemBase; using mozilla::dom::FileSystemRequestParent; using mozilla::dom::MessagePortParent; -using mozilla::dom::NuwaParent; using mozilla::dom::PMessagePortParent; -using mozilla::dom::PNuwaParent; using mozilla::dom::UDPSocketParent; namespace { @@ -297,24 +294,6 @@ BackgroundParentImpl::DeallocPFileDescriptorSetParent( return true; } -PNuwaParent* -BackgroundParentImpl::AllocPNuwaParent() -{ - return mozilla::dom::NuwaParent::Alloc(); -} - -bool -BackgroundParentImpl::RecvPNuwaConstructor(PNuwaParent* aActor) -{ - return mozilla::dom::NuwaParent::ActorConstructed(aActor); -} - -bool -BackgroundParentImpl::DeallocPNuwaParent(PNuwaParent *aActor) -{ - return mozilla::dom::NuwaParent::Dealloc(aActor); -} - PSendStreamParent* BackgroundParentImpl::AllocPSendStreamParent() { diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h index a9082858fc1e4..39c302242c4e9 100644 --- a/ipc/glue/BackgroundParentImpl.h +++ b/ipc/glue/BackgroundParentImpl.h @@ -101,15 +101,6 @@ class BackgroundParentImpl : public PBackgroundParent virtual bool DeallocPBroadcastChannelParent(PBroadcastChannelParent* aActor) override; - virtual PNuwaParent* - AllocPNuwaParent() override; - - virtual bool - RecvPNuwaConstructor(PNuwaParent* aActor) override; - - virtual bool - DeallocPNuwaParent(PNuwaParent* aActor) override; - virtual PSendStreamParent* AllocPSendStreamParent() override; diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index 05a72c0ae7641..f304b0771fec7 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -1227,56 +1227,3 @@ GeckoChildProcessHost::GetQueuedMessages(std::queue& queue) } bool GeckoChildProcessHost::sRunSelfAsContentProc(false); - -#ifdef MOZ_NUWA_PROCESS - -using mozilla::ipc::GeckoExistingProcessHost; -using mozilla::ipc::FileDescriptor; - -GeckoExistingProcessHost:: -GeckoExistingProcessHost(GeckoProcessType aProcessType, - base::ProcessHandle aProcess, - const FileDescriptor& aFileDescriptor, - ChildPrivileges aPrivileges) - : GeckoChildProcessHost(aProcessType, aPrivileges) - , mExistingProcessHandle(aProcess) - , mExistingFileDescriptor(aFileDescriptor) -{ - NS_ASSERTION(aFileDescriptor.IsValid(), - "Expected file descriptor to be valid"); -} - -GeckoExistingProcessHost::~GeckoExistingProcessHost() -{ - // Bug 943174: If we don't do this, ~GeckoChildProcessHost will try - // to wait on a process that isn't a direct child, and bad things - // will happen. - SetAlreadyDead(); -} - -bool -GeckoExistingProcessHost::PerformAsyncLaunch(StringVector aExtraOpts, - base::ProcessArchitecture aArch) -{ - if (!OpenPrivilegedHandle(base::GetProcId(mExistingProcessHandle))) { - NS_RUNTIMEABORT("can't open handle to child process"); - } - - MonitorAutoLock lock(mMonitor); - mProcessState = PROCESS_CREATED; - lock.Notify(); - - return true; -} - -void -GeckoExistingProcessHost::InitializeChannel() -{ - CreateChannel(mExistingFileDescriptor); - - MonitorAutoLock lock(mMonitor); - mProcessState = CHANNEL_INITIALIZED; - lock.Notify(); -} - -#endif /* MOZ_NUWA_PROCESS */ diff --git a/ipc/glue/GeckoChildProcessHost.h b/ipc/glue/GeckoChildProcessHost.h index 269c916ec8c38..c821a6d2b0061 100644 --- a/ipc/glue/GeckoChildProcessHost.h +++ b/ipc/glue/GeckoChildProcessHost.h @@ -212,28 +212,6 @@ class GeckoChildProcessHost : public ChildProcessHost static bool sRunSelfAsContentProc; }; -#ifdef MOZ_NUWA_PROCESS -class GeckoExistingProcessHost final : public GeckoChildProcessHost -{ -public: - GeckoExistingProcessHost(GeckoProcessType aProcessType, - base::ProcessHandle aProcess, - const FileDescriptor& aFileDescriptor, - ChildPrivileges aPrivileges=base::PRIVILEGES_DEFAULT); - - ~GeckoExistingProcessHost(); - - virtual bool PerformAsyncLaunch(StringVector aExtraOpts=StringVector(), - base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()) override; - - virtual void InitializeChannel() override; - -private: - base::ProcessHandle mExistingProcessHandle; - mozilla::ipc::FileDescriptor mExistingFileDescriptor; -}; -#endif /* MOZ_NUWA_PROCESS */ - } /* namespace ipc */ } /* namespace mozilla */ diff --git a/ipc/glue/MessageChannel.h b/ipc/glue/MessageChannel.h index 28fde3338308e..c5282c33b47c6 100644 --- a/ipc/glue/MessageChannel.h +++ b/ipc/glue/MessageChannel.h @@ -201,18 +201,6 @@ class MessageChannel : HasResultCodes sIsPumpingMessages = aIsPumping; } -#ifdef MOZ_NUWA_PROCESS - void Block() { - MOZ_ASSERT(mLink); - mLink->Block(); - } - - void Unblock() { - MOZ_ASSERT(mLink); - mLink->Unblock(); - } -#endif - #ifdef OS_WIN struct MOZ_STACK_CLASS SyncStackFrame { diff --git a/ipc/glue/MessageLink.cpp b/ipc/glue/MessageLink.cpp index 7076653a9ca8f..6a1bda02df6b2 100644 --- a/ipc/glue/MessageLink.cpp +++ b/ipc/glue/MessageLink.cpp @@ -11,18 +11,6 @@ #include "mozilla/ipc/ProtocolUtils.h" #include "chrome/common/ipc_channel.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#include "mozilla/Preferences.h" -#include "mozilla/dom/ContentParent.h" -#include "mozilla/dom/PNuwa.h" -#include "mozilla/hal_sandbox/PHal.h" -#ifdef DEBUG -#include "jsprf.h" -extern "C" char* PrintJSStack(); -#endif -#endif - #include "mozilla/Assertions.h" #include "mozilla/DebugOnly.h" #include "nsDebug.h" @@ -68,10 +56,6 @@ ProcessLink::ProcessLink(MessageChannel *aChan) , mTransport(nullptr) , mIOLoop(nullptr) , mExistingListener(nullptr) -#ifdef MOZ_NUWA_PROCESS - , mIsToNuwaProcess(false) - , mIsBlocked(false) -#endif { } @@ -130,17 +114,6 @@ ProcessLink::Open(mozilla::ipc::Transport* aTransport, MessageLoop *aIOLoop, Sid mIOLoop->PostTask(NewNonOwningRunnableMethod(this, &ProcessLink::OnTakeConnectedChannel)); } -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess() && NS_IsMainThread() && - Preferences::GetBool("dom.ipc.processPrelaunch.testMode")) { - // The pref value is turned on in a deadlock test against the Nuwa - // process. The sleep here makes it easy to trigger the deadlock - // that an IPC channel is still opening but the worker loop is - // already frozen. - sleep(5); - } -#endif - // Should not wait here if something goes wrong with the channel. while (!mChan->Connected() && mChan->mChannelState != ChannelError) { mChan->mMonitor->Wait(); @@ -172,42 +145,6 @@ ProcessLink::SendMessage(Message *msg) mChan->AssertWorkerThread(); mChan->mMonitor->AssertCurrentThreadOwns(); -#ifdef MOZ_NUWA_PROCESS - // Parent to child: check whether we are sending some unexpected message to - // the Nuwa process. - if (mIsToNuwaProcess && mozilla::dom::ContentParent::IsNuwaReady()) { - switch (msg->type()) { - case mozilla::dom::PNuwa::Msg_Fork__ID: - case mozilla::dom::PNuwa::Reply_AddNewProcess__ID: - case mozilla::dom::PContent::Msg_NotifyPhoneStateChange__ID: - case mozilla::dom::PContent::Msg_ActivateA11y__ID: - case mozilla::hal_sandbox::PHal::Msg_NotifyNetworkChange__ID: - case GOODBYE_MESSAGE_TYPE: - break; - default: -#ifdef DEBUG - MOZ_CRASH(); -#else - // In optimized build, message will be dropped. - printf_stderr("Sending message to frozen Nuwa"); - return; -#endif - } - } - -#if defined(DEBUG) - // Nuwa to parent: check whether we are currently blocked. - if (IsNuwaProcess() && mIsBlocked) { - char* jsstack = PrintJSStack(); - printf_stderr("Fatal error: sending a message to the chrome process" - "with a blocked IPC channel from \n%s", - jsstack ? jsstack : ""); - JS_smprintf_free(jsstack); - MOZ_CRASH(); - } -#endif -#endif - mIOLoop->PostTask(NewNonOwningRunnableMethod(mTransport, &Transport::Send, msg)); } @@ -397,10 +334,6 @@ ProcessLink::OnChannelConnected(int32_t peer_pid) if (mExistingListener) mExistingListener->OnChannelConnected(peer_pid); -#ifdef MOZ_NUWA_PROCESS - mIsToNuwaProcess = (peer_pid == mozilla::dom::ContentParent::NuwaPid()); -#endif - if (notifyChannel) { mChan->OnChannelConnected(peer_pid); } diff --git a/ipc/glue/MessageLink.h b/ipc/glue/MessageLink.h index aa189bb858109..824221d2239bc 100644 --- a/ipc/glue/MessageLink.h +++ b/ipc/glue/MessageLink.h @@ -163,12 +163,6 @@ class MessageLink virtual bool Unsound_IsClosed() const = 0; virtual uint32_t Unsound_NumQueuedMessages() const = 0; -#ifdef MOZ_NUWA_PROCESS - // To be overridden by ProcessLink. - virtual void Block() {} - virtual void Unblock() {} -#endif - protected: MessageChannel *mChan; }; @@ -216,23 +210,10 @@ class ProcessLink virtual bool Unsound_IsClosed() const override; virtual uint32_t Unsound_NumQueuedMessages() const override; -#ifdef MOZ_NUWA_PROCESS - void Block() override { - mIsBlocked = true; - } - void Unblock() override { - mIsBlocked = false; - } -#endif - protected: Transport* mTransport; MessageLoop* mIOLoop; // thread where IO happens Transport::Listener* mExistingListener; // channel's previous listener -#ifdef MOZ_NUWA_PROCESS - bool mIsToNuwaProcess; - bool mIsBlocked; -#endif }; class ThreadLink : public MessageLink diff --git a/ipc/glue/MessagePump.cpp b/ipc/glue/MessagePump.cpp index 842a547af2a94..15c17b8f4d1d9 100644 --- a/ipc/glue/MessagePump.cpp +++ b/ipc/glue/MessagePump.cpp @@ -25,10 +25,6 @@ #include "nsXULAppAPI.h" #include "prthread.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - using base::TimeTicks; using namespace mozilla::ipc; @@ -108,11 +104,7 @@ MessagePump::Run(MessagePump::Delegate* aDelegate) did_work |= aDelegate->DoDelayedWork(&delayed_work_time_); -if (did_work && delayed_work_time_.is_null() -#ifdef MOZ_NUWA_PROCESS - && (!IsNuwaReady() || !IsNuwaProcess()) -#endif - ) +if (did_work && delayed_work_time_.is_null()) mDelayedWorkTimer->Cancel(); if (!keep_running_) @@ -132,9 +124,6 @@ if (did_work && delayed_work_time_.is_null() NS_ProcessNextEvent(thisThread, true); } -#ifdef MOZ_NUWA_PROCESS - if (!IsNuwaReady() || !IsNuwaProcess()) -#endif mDelayedWorkTimer->Cancel(); keep_running_ = true; @@ -166,11 +155,6 @@ MessagePump::ScheduleWorkForNestedLoop() void MessagePump::ScheduleDelayedWork(const base::TimeTicks& aDelayedTime) { -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaReady() && IsNuwaProcess()) - return; -#endif - // To avoid racing on mDelayedWorkTimer, we need to be on the same thread as // ::Run(). MOZ_RELEASE_ASSERT(NS_GetCurrentThread() == mThread || diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl index 892d4bdbb6586..eacb427694d18 100644 --- a/ipc/glue/PBackground.ipdl +++ b/ipc/glue/PBackground.ipdl @@ -17,7 +17,6 @@ include protocol PGamepadEventChannel; include protocol PGamepadTestChannel; include protocol PMessagePort; include protocol PCameras; -include protocol PNuwa; include protocol PQuota; include protocol PSendStream; include protocol PServiceWorkerManager; @@ -61,7 +60,6 @@ sync protocol PBackground manages PGamepadTestChannel; manages PMessagePort; manages PCameras; - manages PNuwa; manages PQuota; manages PSendStream; manages PServiceWorkerManager; @@ -94,8 +92,6 @@ parent: async PMessagePort(nsID uuid, nsID destinationUuid, uint32_t sequenceId); - async PNuwa(); - async PSendStream(); async MessagePortForceClose(nsID uuid, nsID destinationUuid, uint32_t sequenceId); diff --git a/ipc/glue/ProcessUtils.h b/ipc/glue/ProcessUtils.h index aad173d4423d6..2908d9876cbaf 100644 --- a/ipc/glue/ProcessUtils.h +++ b/ipc/glue/ProcessUtils.h @@ -7,10 +7,6 @@ #ifndef mozilla_ipc_ProcessUtils_h #define mozilla_ipc_ProcessUtils_h -#ifdef MOZ_B2G_LOADER -#include "base/process_util.h" -#endif - namespace mozilla { namespace ipc { @@ -18,17 +14,6 @@ namespace ipc { // this directly. void SetThisProcessName(const char *aName); -#ifdef MOZ_B2G_LOADER -// see ProcessUtils_linux.cpp for explaination. -void ProcLoaderClientGeckoInit(); -bool ProcLoaderIsInitialized(); -bool ProcLoaderLoad(const char *aArgv[], - const char *aEnvp[], - const base::file_handle_mapping_vector &aFdsRemap, - const base::ChildPrivileges aPrivs, - base::ProcessHandle *aProcessHandle); -#endif /* MOZ_B2G_LOADER */ - } // namespace ipc } // namespace mozilla diff --git a/ipc/glue/ProcessUtils_linux.cpp b/ipc/glue/ProcessUtils_linux.cpp index 60f03e828e875..d95527a4fb326 100644 --- a/ipc/glue/ProcessUtils_linux.cpp +++ b/ipc/glue/ProcessUtils_linux.cpp @@ -10,41 +10,6 @@ #include -#ifdef MOZ_B2G_LOADER - -#include -#include - -#include "nsAutoPtr.h" - -#include "mozilla/Assertions.h" -#include "mozilla/ipc/PProcLoaderParent.h" -#include "mozilla/ipc/PProcLoaderChild.h" -#include "mozilla/ipc/Transport.h" -#include "mozilla/ipc/FileDescriptorUtils.h" -#include "mozilla/ipc/IOThreadChild.h" -#include "mozilla/dom/ContentProcess.h" -#include "base/file_descriptor_shuffle.h" -#include "mozilla/BackgroundHangMonitor.h" -#include "mozilla/DebugOnly.h" -#include "mozilla/UniquePtr.h" -#include "mozilla/unused.h" -#include "base/process_util.h" -#include "base/eintr_wrapper.h" -#include "mozilla/Preferences.h" - -#include "prenv.h" - -#include "nsXULAppAPI.h" // export XRE_* functions - -#include "nsAppRunner.h" - -int content_process_main(int argc, char *argv[]); - -typedef mozilla::Vector FdArray; - -#endif /* MOZ_B2G_LOADER */ - namespace mozilla { namespace ipc { @@ -54,574 +19,6 @@ void SetThisProcessName(const char *aName) prctl(PR_SET_NAME, (unsigned long)aName, 0uL, 0uL, 0uL); } -#ifdef MOZ_B2G_LOADER -/** - * How does B2G Loader Work? - * - * <> <> - * ProcLoaderParent -----> ProcLoaderChild - * ^ | - * | load() | content_process_main() - * | V - * ProcLoaderClient Nuwa/plugin-container - * ^ - * | ProcLoaderLoad() - * ... - * ContentParent - * - * - * B2G loader includes an IPC protocol PProcLoader for communication - * between client (parent) and server (child). The b2g process is the - * client. It requests the server to load/start the Nuwa process with - * the given arguments, env variables, and file descriptors. - * - * ProcLoaderClientInit() is called by B2G loader to initialize the - * client side, the b2g process. Then the b2g_main() is called to - * start b2g process. - * - * ProcLoaderClientGeckoInit() is called by XRE_main() to create the - * parent actor, |ProcLoaderParent|, of PProcLoader for servicing the - * request to run Nuwa process later once Gecko has been initialized. - * - * ProcLoaderServiceRun() is called by the server process. It starts - * an IOThread and event loop to serve the |ProcLoaderChild| - * implmentation of PProcLoader protocol as the child actor. Once it - * recieves a load() request, it stops the IOThread and event loop, - * then starts running the main function of the content process with - * the given arguments. - * - * NOTE: The server process serves at most one load() request. - */ - -using namespace mozilla::dom; - -using base::ChildPrivileges; -using base::InjectionArc; -using base::InjectiveMultimap; -using base::ProcessHandle; -using base::ProcessId; -using base::SetCurrentProcessPrivileges; -using base::ShuffleFileDescriptors; -using base::file_handle_mapping_vector; - -static bool sProcLoaderClientOnDeinit = false; -static DebugOnly sProcLoaderClientInitialized = false; -static DebugOnly sProcLoaderClientGeckoInitialized = false; -static pid_t sProcLoaderPid = 0; -static int sProcLoaderChannelFd = -1; -static PProcLoaderParent *sProcLoaderParent = nullptr; -static MessageLoop *sProcLoaderLoop = nullptr; -static mozilla::UniquePtr sReservedFds; - -static void ProcLoaderClientDeinit(); - -/** - * Some file descriptors, like the child IPC channel FD, must be opened at - * specific numbers. To ensure this, we pre-reserve kReservedFileDescriptors FDs - * starting from kBeginReserveFileDescriptor so that operations like - * __android_log_print() won't take these magic FDs. - */ -static const size_t kReservedFileDescriptors = 5; -static const int kBeginReserveFileDescriptor = STDERR_FILENO + 1; - -class ProcLoaderParent : public PProcLoaderParent -{ -public: - ProcLoaderParent() {} - virtual ~ProcLoaderParent() {} - - virtual void ActorDestroy(ActorDestroyReason aWhy) override; - - virtual bool RecvLoadComplete(const int32_t &aPid, - const int32_t &aCookie) override; -}; - -void -ProcLoaderParent::ActorDestroy(ActorDestroyReason aWhy) -{ - if (aWhy == AbnormalShutdown) { - NS_WARNING("ProcLoaderParent is destroyed abnormally."); - } - - if (sProcLoaderClientOnDeinit) { - // Get error for closing while the channel is already error. - return; - } - - // Destroy self asynchronously. - ProcLoaderClientDeinit(); -} - -static void -_ProcLoaderParentDestroy(PProcLoaderParent *aLoader) -{ - delete aLoader; - sProcLoaderClientOnDeinit = false; -} - -bool -ProcLoaderParent::RecvLoadComplete(const int32_t &aPid, - const int32_t &aCookie) -{ - return true; -} - -static void -CloseFileDescriptors(FdArray& aFds) -{ - for (size_t i = 0; i < aFds.length(); i++) { - Unused << HANDLE_EINTR(close(aFds[i])); - } -} - -/** - * Initialize the client of B2G loader for loader itself. - * - * The initialization of B2G loader are divided into two stages. First - * stage is to collect child info passed from the main program of the - * loader. Second stage is to initialize Gecko according to info from the - * first stage and make the client of loader service ready. - * - * \param aPeerPid is the pid of the child. - * \param aChannelFd is the file descriptor of the socket used for IPC. - */ -static void -ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd) -{ - MOZ_ASSERT(!sProcLoaderClientInitialized, "call ProcLoaderClientInit() more than once"); - MOZ_ASSERT(aPeerPid != 0 && aChannelFd != -1, "invalid argument"); - sProcLoaderPid = aPeerPid; - sProcLoaderChannelFd = aChannelFd; - sProcLoaderClientInitialized = true; -} - -/** - * Initialize the client of B2G loader for Gecko. - */ -void -ProcLoaderClientGeckoInit() -{ - MOZ_ASSERT(sProcLoaderClientInitialized, "call ProcLoaderClientInit() at first"); - MOZ_ASSERT(!sProcLoaderClientGeckoInitialized, - "call ProcLoaderClientGeckoInit() more than once"); - - if (!Preferences::GetBool("dom.ipc.processPrelaunch.enabled", false)) { - kill(sProcLoaderPid, SIGKILL); - sProcLoaderPid = 0; - close(sProcLoaderChannelFd); - sProcLoaderChannelFd = -1; - return; - } - - sProcLoaderClientGeckoInitialized = true; - - TransportDescriptor fd; - fd.mFd = base::FileDescriptor(sProcLoaderChannelFd, /*auto_close=*/ false); - sProcLoaderChannelFd = -1; - UniquePtr transport = OpenDescriptor(fd, Transport::MODE_CLIENT); - sProcLoaderParent = new ProcLoaderParent(); - sProcLoaderParent->Open(transport.get(), - sProcLoaderPid, - XRE_GetIOMessageLoop(), - ParentSide); - sProcLoaderLoop = MessageLoop::current(); -} - -bool ProcLoaderIsInitialized() -{ - return sProcLoaderPid != 0; -} - -/** - * Shutdown and destroy the client of B2G loader service. - */ -static void -ProcLoaderClientDeinit() -{ - MOZ_ASSERT(sProcLoaderClientGeckoInitialized && sProcLoaderClientInitialized); - sProcLoaderClientGeckoInitialized = false; - sProcLoaderClientInitialized = false; - - sProcLoaderClientOnDeinit = true; - - MOZ_ASSERT(sProcLoaderParent != nullptr); - PProcLoaderParent *procLoaderParent = sProcLoaderParent; - sProcLoaderParent = nullptr; - sProcLoaderLoop = nullptr; - - MessageLoop::current()-> - PostTask(NewRunnableFunction(&_ProcLoaderParentDestroy, - procLoaderParent)); -} - -struct AsyncSendLoadData -{ - nsTArray mArgv; - nsTArray mEnv; - nsTArray mFdsremap; - ChildPrivileges mPrivs; - int mCookie; -}; - -static void -AsyncSendLoad(AsyncSendLoadData *aLoad) -{ - PProcLoaderParent *loader = sProcLoaderParent; - DebugOnly ok = - loader->SendLoad(aLoad->mArgv, aLoad->mEnv, aLoad->mFdsremap, - aLoad->mPrivs, aLoad->mCookie); - MOZ_ASSERT(ok); - delete aLoad; -} - -/** - * Request the loader service, the server, to load Nuwa. - */ -bool -ProcLoaderLoad(const char *aArgv[], - const char *aEnvp[], - const file_handle_mapping_vector &aFdsRemap, - const ChildPrivileges aPrivs, - ProcessHandle *aProcessHandle) -{ - static int cookie=0; - int i; - - if (sProcLoaderParent == nullptr || sProcLoaderPid == 0) { - return false; - } - - AsyncSendLoadData *load = new AsyncSendLoadData(); - nsTArray &argv = load->mArgv; - for (i = 0; aArgv[i] != nullptr; i++) { - argv.AppendElement(nsCString(aArgv[i])); - } - nsTArray &env = load->mEnv; - for (i = 0; aEnvp[i] != nullptr; i++) { - env.AppendElement(nsCString(aEnvp[i])); - } - nsTArray &fdsremap = load->mFdsremap; - for (file_handle_mapping_vector::const_iterator fdmap = - aFdsRemap.begin(); - fdmap != aFdsRemap.end(); - fdmap++) { - fdsremap.AppendElement(FDRemap(FileDescriptor(fdmap->first), fdmap->second)); - } - load->mPrivs = aPrivs; - load->mCookie = cookie++; - - *aProcessHandle = sProcLoaderPid; - sProcLoaderPid = 0; - - sProcLoaderLoop->PostTask(NewRunnableFunction(AsyncSendLoad, load)); - return true; -} - - -class ProcLoaderRunnerBase; - -static bool sProcLoaderServing = false; -static ProcLoaderRunnerBase *sProcLoaderDispatchedTask = nullptr; - -class ProcLoaderRunnerBase -{ -public: - virtual int DoWork() = 0; - virtual ~ProcLoaderRunnerBase() {} -}; - - -class ProcLoaderNoopRunner : public ProcLoaderRunnerBase { -public: - virtual int DoWork(); -}; - -int -ProcLoaderNoopRunner::DoWork() { - return 0; -} - -/** - * The runner to load Nuwa at the current process. - */ -class ProcLoaderLoadRunner : public ProcLoaderRunnerBase { -private: - const nsTArray mArgv; - const nsTArray mEnv; - const nsTArray mFdsRemap; - const ChildPrivileges mPrivs; - - void ShuffleFds(); - -public: - ProcLoaderLoadRunner(const InfallibleTArray& aArgv, - const InfallibleTArray& aEnv, - const InfallibleTArray& aFdsRemap, - const ChildPrivileges aPrivs) - : mArgv(aArgv) - , mEnv(aEnv) - , mFdsRemap(aFdsRemap) - , mPrivs(aPrivs) {} - - int DoWork(); -}; - -void -ProcLoaderLoadRunner::ShuffleFds() -{ - unsigned int i; - - MOZ_ASSERT(mFdsRemap.Length() <= kReservedFileDescriptors); - - InjectiveMultimap fd_shuffle; - fd_shuffle.reserve(mFdsRemap.Length()); - - for (i = 0; i < mFdsRemap.Length(); i++) { - const FDRemap *map = &mFdsRemap[i]; - auto rawFD = map->fd().ClonePlatformHandle(); - int tofd = map->mapto(); - - // The FD that is dup2()'d from needs to be closed after shuffling. - fd_shuffle.push_back(InjectionArc(rawFD.get(), tofd, /*in_close=*/true)); - - // Erase from sReservedFds we will use. - for (int* toErase = sReservedFds->begin(); - toErase < sReservedFds->end(); - toErase++) { - if (tofd == *toErase) { - sReservedFds->erase(toErase); - break; - } - } - } - - DebugOnly ok = ShuffleFileDescriptors(&fd_shuffle); - - // Close the FDs that are reserved but not used after - // ShuffleFileDescriptors(). - MOZ_ASSERT(sReservedFds); - CloseFileDescriptors(*sReservedFds); - sReservedFds = nullptr; - - // Note that we don'e call ::base::CloseSuperfluousFds() here, assuming that - // The file descriptor inherited from the parent are also necessary for us. -} - -int -ProcLoaderLoadRunner::DoWork() -{ - unsigned int i; - - ShuffleFds(); - - unsigned int argc = mArgv.Length(); - char **argv = new char *[argc + 1]; - for (i = 0; i < argc; i++) { - argv[i] = ::strdup(mArgv[i].get()); - } - argv[argc] = nullptr; - - unsigned int envc = mEnv.Length(); - for (i = 0; i < envc; i++) { - PR_SetEnv(mEnv[i].get()); - } - - SetCurrentProcessPrivileges(mPrivs); - - // Start Nuwa (main function) - int ret = content_process_main(argc, argv); - - for (i = 0; i < argc; i++) { - free(argv[i]); - } - delete[] argv; - - return ret; -} - - -class ProcLoaderChild : public PProcLoaderChild -{ - pid_t mPeerPid; - -public: - ProcLoaderChild(pid_t aPeerPid) : mPeerPid(aPeerPid) {} - - virtual void ActorDestroy(ActorDestroyReason aWhy) override; - - virtual bool RecvLoad(InfallibleTArray&& aArgv, - InfallibleTArray&& aEnv, - InfallibleTArray&& aFdsremap, - const uint32_t& aPrivs, - const int32_t& aCookie); - - virtual void OnChannelError(); -}; - -void -ProcLoaderChild::ActorDestroy(ActorDestroyReason aWhy) -{ -} - -static void -_ProcLoaderChildDestroy(ProcLoaderChild *aChild) -{ - aChild->Close(); - delete aChild; - MessageLoop::current()->Quit(); -} - -bool -ProcLoaderChild::RecvLoad(InfallibleTArray&& aArgv, - InfallibleTArray&& aEnv, - InfallibleTArray&& aFdsRemap, - const uint32_t& aPrivs, - const int32_t& aCookie) { - if (!sProcLoaderServing) { - return true; - } - sProcLoaderServing = false; - - MOZ_ASSERT(sProcLoaderDispatchedTask == nullptr); - ChildPrivileges privs = static_cast(aPrivs); - sProcLoaderDispatchedTask = - new ProcLoaderLoadRunner(aArgv, aEnv, aFdsRemap, privs); - - SendLoadComplete(mPeerPid, aCookie); - - MessageLoop::current()->PostTask( - NewRunnableFunction(_ProcLoaderChildDestroy, this)); - return true; -} - -void -ProcLoaderChild::OnChannelError() -{ - if (!sProcLoaderServing) { - return; - } - sProcLoaderServing = false; - - PProcLoaderChild::OnChannelError(); - - MOZ_ASSERT(sProcLoaderDispatchedTask == nullptr); - sProcLoaderDispatchedTask = new ProcLoaderNoopRunner(); - - MessageLoop::current()->PostTask( - NewRunnableFunction(_ProcLoaderChildDestroy, this)); -} - -/** - * A helper class which calls NS_LogInit/NS_LogTerm in its scope. - */ -class ScopedLogging -{ -public: - ScopedLogging() { NS_LogInit(); } - ~ScopedLogging() { NS_LogTerm(); } -}; - -/** - * Run service of ProcLoader. - * - * \param aPeerPid is the pid of the parent. - * \param aFd is the file descriptor of the socket for IPC. - * - * See the comment near the head of this file. - */ -static int -ProcLoaderServiceRun(pid_t aPeerPid, int aFd, - int aArgc, const char *aArgv[], - FdArray& aReservedFds) -{ - // Make a copy of aReservedFds. It will be used when we dup() the magic file - // descriptors when ProcLoaderChild::RecvLoad() runs. - sReservedFds = MakeUnique(mozilla::Move(aReservedFds)); - - ScopedLogging logging; - - char **_argv; - _argv = new char *[aArgc + 1]; - for (int i = 0; i < aArgc; i++) { - _argv[i] = ::strdup(aArgv[i]); - MOZ_ASSERT(_argv[i] != nullptr); - } - _argv[aArgc] = nullptr; - - gArgv = _argv; - gArgc = aArgc; - - { - nsresult rv = XRE_InitCommandLine(aArgc, _argv); - if (NS_FAILED(rv)) { - MOZ_CRASH(); - } - - mozilla::LogModule::Init(); - - TransportDescriptor fd; - fd.mFd = base::FileDescriptor(aFd, /*auto_close =*/false); - - MOZ_ASSERT(!sProcLoaderServing); - MessageLoop loop; - - nsAutoPtr process; - process = new ContentProcess(aPeerPid); - ChildThread *iothread = process->child_thread(); - - UniquePtr transport = OpenDescriptor(fd, Transport::MODE_CLIENT); - ProcLoaderChild *loaderChild = new ProcLoaderChild(aPeerPid); - // Pass a message loop to initialize (connect) the channel - // (connection). - loaderChild->Open(transport.get(), aPeerPid, iothread->message_loop()); - - BackgroundHangMonitor::Prohibit(); - - sProcLoaderServing = true; - loop.Run(); - - BackgroundHangMonitor::Allow(); - - XRE_DeinitCommandLine(); - } - - MOZ_ASSERT(sProcLoaderDispatchedTask != nullptr); - ProcLoaderRunnerBase *task = sProcLoaderDispatchedTask; - sProcLoaderDispatchedTask = nullptr; - int ret = task->DoWork(); - delete task; - - for (int i = 0; i < aArgc; i++) { - free(_argv[i]); - } - delete[] _argv; - - return ret; -} - -#endif /* MOZ_B2G_LOADER */ } // namespace ipc } // namespace mozilla - -#ifdef MOZ_B2G_LOADER -void -XRE_ProcLoaderClientInit(pid_t aPeerPid, int aChannelFd, FdArray& aReservedFds) -{ - // We already performed fork(). It's safe to free the "danger zone" of file - // descriptors . - mozilla::ipc::CloseFileDescriptors(aReservedFds); - - mozilla::ipc::ProcLoaderClientInit(aPeerPid, aChannelFd); -} - -int -XRE_ProcLoaderServiceRun(pid_t aPeerPid, int aFd, - int aArgc, const char *aArgv[], - FdArray& aReservedFds) -{ - return mozilla::ipc::ProcLoaderServiceRun(aPeerPid, aFd, - aArgc, aArgv, - aReservedFds); -} -#endif /* MOZ_B2G_LOADER */ diff --git a/js/src/old-configure.in b/js/src/old-configure.in index c1e7bd93305d3..ca229145fd28c 100644 --- a/js/src/old-configure.in +++ b/js/src/old-configure.in @@ -2357,10 +2357,6 @@ HOST_CXXFLAGS=`echo \ AC_SUBST(_DEPEND_CFLAGS) AC_SUBST(MOZ_SYSTEM_NSPR) -if test -n "$MOZ_NUWA_PROCESS"; then - AC_DEFINE(MOZ_NUWA_PROCESS) -fi - OS_CFLAGS="$CFLAGS" OS_CXXFLAGS="$CXXFLAGS" OS_CPPFLAGS="$CPPFLAGS" diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index 7dd0ed203d97d..cf713d815dd0d 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -1296,26 +1296,12 @@ HelperThread::destroy() threadData.reset(); } -#ifdef MOZ_NUWA_PROCESS -extern "C" { -MFBT_API bool IsNuwaProcess(); -MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void*), void* arg); -} -#endif - /* static */ void HelperThread::ThreadMain(void* arg) { PR_SetCurrentThreadName("JS Helper"); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - MOZ_ASSERT(NuwaMarkCurrentThread != nullptr); - NuwaMarkCurrentThread(nullptr, nullptr); - } -#endif - //See bug 1104658. //Set the FPU control word to be the same as the main thread's, or math //computations on this thread may use incorrect precision rules during diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 0b77250c34124..54715e8d509b7 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1121,10 +1121,6 @@ class Watchdog mozilla::Atomic mMinScriptRunTimeSeconds; }; -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - #define PREF_MAX_SCRIPT_RUN_TIME_CONTENT "dom.max_script_run_time" #define PREF_MAX_SCRIPT_RUN_TIME_CHROME "dom.max_chrome_script_run_time" @@ -1282,13 +1278,6 @@ WatchdogMain(void* arg) { PR_SetCurrentThreadName("JS Watchdog"); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - NuwaFreezeCurrentThread(); - } -#endif - Watchdog* self = static_cast(arg); WatchdogManager* manager = self->Manager(); diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index a347c75b4ccf2..db77b8c9406f0 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -69,10 +69,6 @@ #include "nsAnimationManager.h" #include "nsIDOMEvent.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - using namespace mozilla; using namespace mozilla::widget; using namespace mozilla::ipc; @@ -865,15 +861,6 @@ CreateVsyncRefreshTimer() return; } -#ifdef MOZ_NUWA_PROCESS - // NUWA process will just use software timer. Use NuwaAddFinalConstructor() - // to register a callback to create the vsync-base refresh timer after a - // process is created. - if (IsNuwaProcess()) { - NuwaAddFinalConstructor(&CreateContentVsyncRefreshTimer, nullptr); - return; - } -#endif // If this process is not created by NUWA, just create the vsync timer here. CreateContentVsyncRefreshTimer(nullptr); } diff --git a/memory/jemalloc/moz.build b/memory/jemalloc/moz.build index 935b761944c6e..ff4163fc8f184 100644 --- a/memory/jemalloc/moz.build +++ b/memory/jemalloc/moz.build @@ -64,9 +64,6 @@ if CONFIG['OS_TARGET'] == 'Linux': # For mremap DEFINES['_GNU_SOURCE'] = True -if CONFIG['MOZ_NUWA_PROCESS'] and CONFIG['MOZ_JEMALLOC4']: - DEFINES['pthread_mutex_lock'] = '__real_pthread_mutex_lock' - if CONFIG['GNU_CC']: CFLAGS += ['-std=gnu99'] diff --git a/memory/mozjemalloc/moz.build b/memory/mozjemalloc/moz.build index 946753d971801..d9f98e99ed968 100644 --- a/memory/mozjemalloc/moz.build +++ b/memory/mozjemalloc/moz.build @@ -35,9 +35,6 @@ DEFINES['MOZ_JEMALLOC_IMPL'] = True if CONFIG['OS_TARGET'] == 'Linux': NO_PGO = True -if CONFIG['MOZ_NUWA_PROCESS']: - DEFINES['pthread_mutex_lock'] = '__real_pthread_mutex_lock'; - LOCAL_INCLUDES += [ '/memory/build', ] diff --git a/memory/replace/dmd/DMD.cpp b/memory/replace/dmd/DMD.cpp index 8e1e6c2df3fc1..49eb2797020b9 100644 --- a/memory/replace/dmd/DMD.cpp +++ b/memory/replace/dmd/DMD.cpp @@ -259,11 +259,6 @@ void DMDFuncs::StatusMsg(const char* aFmt, va_list aAp) { #ifdef ANDROID -#ifdef MOZ_B2G_LOADER - // Don't call __android_log_vprint() during initialization, or the magic file - // descriptors will be occupied by android logcat. - if (gIsDMDInitialized) -#endif __android_log_vprint(ANDROID_LOG_INFO, "DMD", aFmt, aAp); #else // The +64 is easily enough for the "DMD[] " prefix and the NUL. diff --git a/memory/replace/logalloc/replay/Replay.cpp b/memory/replace/logalloc/replay/Replay.cpp index 512f76d585028..a58f8bf972a3c 100644 --- a/memory/replace/logalloc/replay/Replay.cpp +++ b/memory/replace/logalloc/replay/Replay.cpp @@ -307,18 +307,6 @@ pthread_atfork(void (*aPrepare)(void), void (*aParent)(void), } #endif -#ifdef MOZ_NUWA_PROCESS -#include - -/* NUWA builds have jemalloc built with - * -Dpthread_mutex_lock=__real_pthread_mutex_lock */ -int -__real_pthread_mutex_lock(pthread_mutex_t* aMutex) -{ - return pthread_mutex_lock(aMutex); -} -#endif - MOZ_END_EXTERN_C size_t parseNumber(Buffer aBuf) diff --git a/mozglue/build/Nuwa.cpp b/mozglue/build/Nuwa.cpp deleted file mode 100644 index 4be83e699609b..0000000000000 --- a/mozglue/build/Nuwa.cpp +++ /dev/null @@ -1,2104 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mozilla/Alignment.h" -#include "mozilla/LinkedList.h" -#include "mozilla/TaggedAnonymousMemory.h" -#include "Nuwa.h" - - -/* Support for telling Valgrind about the stack pointer changes that - Nuwa makes. Without this, Valgrind is unusable in Nuwa child - processes due to the large number of false positives resulting from - Nuwa's stack pointer changes. See bug 1125091. -*/ - -#if defined(MOZ_VALGRIND) -# include -#endif - -#define DEBUG_VALGRIND_ANNOTATIONS 1 - -/* Call this as soon as possible after a setjmp() that has returned - non-locally (that is, it is restoring some previous context). This - paints a small area -- half a page -- above SP as containing - defined data in any area which is currently marked accessible. - - Note that in fact there are a few memory references to the stack - after the setjmp but before the use of this macro, even when they - appear consecutively in the source code. But those accesses all - appear to be stores, and since that part of the stack -- before we - get to the VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE client request - -- is marked as accessible-but-undefined, Memcheck doesn't - complain. Of course, once we get past the client request then even - reading from the stack is "safe". - - VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE and VALGRIND_PRINTF each - require 6 words of stack space. In the worst case, in which the - compiler allocates two different pieces of stack, the required - extra stack is therefore 12 words, that is, 48 bytes on arm32. -*/ -#if defined(MOZ_VALGRIND) && defined(VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE) \ - && defined(__arm__) && !defined(__aarch64__) -# define POST_SETJMP_RESTORE(_who) \ - do { \ - /* setjmp returned 1 (meaning "restored"). Paint the area */ \ - /* immediately above SP as "defined where it is accessible". */ \ - register unsigned long int sp; \ - __asm__ __volatile__("mov %0, sp" : "=r"(sp)); \ - unsigned long int len = 1024*2; \ - VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(sp, len); \ - if (DEBUG_VALGRIND_ANNOTATIONS) { \ - VALGRIND_PRINTF("Nuwa: POST_SETJMP_RESTORE: marking [0x%lx, +%ld) as " \ - "Defined-if-Addressible, called by %s\n", \ - sp, len, (_who)); \ - } \ - } while (0) -#else -# define POST_SETJMP_RESTORE(_who) /* */ -#endif - - -using namespace mozilla; - -/** - * Provides the wrappers to a selected set of pthread and system-level functions - * as the basis for implementing Zygote-like preforking mechanism. - */ - -/** - * Real functions for the wrappers. - */ -extern "C" { -#pragma GCC visibility push(default) -int __real_pthread_create(pthread_t *thread, - const pthread_attr_t *attr, - void *(*start_routine) (void *), - void *arg); -int __real_pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); -int __real_pthread_key_delete(pthread_key_t key); -pthread_t __real_pthread_self(); -int __real_pthread_join(pthread_t thread, void **retval); -int __real_epoll_wait(int epfd, - struct epoll_event *events, - int maxevents, - int timeout); -int __real_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mtx); -int __real_pthread_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t *mtx, - const struct timespec *abstime); -int __real_pthread_mutex_lock(pthread_mutex_t *mtx); -int __real_pthread_mutex_trylock(pthread_mutex_t *mtx); -int __real_poll(struct pollfd *fds, nfds_t nfds, int timeout); -int __real_epoll_create(int size); -int __real_socketpair(int domain, int type, int protocol, int sv[2]); -int __real_pipe2(int __pipedes[2], int flags); -int __real_pipe(int __pipedes[2]); -int __real_epoll_ctl(int aEpollFd, int aOp, int aFd, struct epoll_event *aEvent); -int __real_close(int aFd); -#pragma GCC visibility pop -} - -#define REAL(s) __real_##s - -/** - * A Nuwa process is started by preparing. After preparing, it waits - * for all threads becoming frozen. Then, it is ready while all - * threads are frozen. - */ -static bool sIsNuwaProcess = false; // This process is a Nuwa process. -static bool sIsNuwaChildProcess = false; // This process is spawned from Nuwa. -static bool sIsFreezing = false; // Waiting for all threads getting frozen. -static bool sNuwaReady = false; // Nuwa process is ready. -static bool sNuwaPendingSpawn = false; // Are there any pending spawn requests? -static bool sNuwaForking = false; - -// Fds of transports of top level protocols. -static NuwaProtoFdInfo sProtoFdInfos[NUWA_TOPLEVEL_MAX]; -static int sProtoFdInfosSize = 0; - -typedef std::vector > -TLSInfoList; - -/** - * Return the system's page size - */ -static size_t getPageSize(void) { -#ifdef HAVE_GETPAGESIZE - return getpagesize(); -#elif defined(_SC_PAGESIZE) - return sysconf(_SC_PAGESIZE); -#elif defined(PAGE_SIZE) - return PAGE_SIZE; -#else - #warning "Hard-coding page size to 4096 bytes" - return 4096 -#endif -} - -/** - * Use 1 MiB stack size as Android does. - */ -#ifndef NUWA_STACK_SIZE -#define NUWA_STACK_SIZE (1024 * 1024) -#endif - -#define NATIVE_THREAD_NAME_LENGTH 16 - -typedef struct nuwa_construct { - typedef void(*construct_t)(void*); - - construct_t construct; - void *arg; - - nuwa_construct(construct_t aConstruct, void *aArg) - : construct(aConstruct) - , arg(aArg) - { } - - nuwa_construct(const nuwa_construct&) = default; - nuwa_construct& operator=(const nuwa_construct&) = default; - -} nuwa_construct_t; - -struct thread_info : public mozilla::LinkedListElement { - pthread_t origThreadID; - pthread_t recreatedThreadID; - pthread_attr_t threadAttr; - jmp_buf jmpEnv; - jmp_buf retEnv; - - int flags; - - void *(*startupFunc)(void *arg); - void *startupArg; - - // The thread specific function to recreate the new thread. It's executed - // after the thread is recreated. - - std::vector *recrFunctions; - void addThreadConstructor(const nuwa_construct_t *construct) { - if (!recrFunctions) { - recrFunctions = new std::vector(); - } - - recrFunctions->push_back(*construct); - } - - TLSInfoList tlsInfo; - - /** - * We must ensure that the recreated thread has entered pthread_cond_wait() or - * similar functions before proceeding to recreate the next one. Otherwise, if - * the next thread depends on the same mutex, it may be used in an incorrect - * state. To do this, the main thread must unconditionally acquire the mutex. - * The mutex is unconditionally released when the recreated thread enters - * pthread_cond_wait(). The recreated thread may have locked the mutex itself - * (if the pthread_mutex_trylock succeeded) or another thread may have already - * held the lock. If the recreated thread did lock the mutex we must balance - * that with another unlock on the main thread, which is signaled by - * condMutexNeedsBalancing. - */ - pthread_mutex_t *condMutex; - bool condMutexNeedsBalancing; - - size_t stackSize; - size_t guardSize; - void *stk; - - pid_t origNativeThreadID; - pid_t recreatedNativeThreadID; - char nativeThreadName[NATIVE_THREAD_NAME_LENGTH]; -}; - -typedef struct thread_info thread_info_t; - -static thread_info_t *sCurrentRecreatingThread = nullptr; - -/** - * This function runs the custom recreation function registered when calling - * NuwaMarkCurrentThread() after thread stack is restored. - */ -static void -RunCustomRecreation() { - thread_info_t *tinfo = sCurrentRecreatingThread; - if (tinfo->recrFunctions) { - for (auto iter = tinfo->recrFunctions->begin(); - iter != tinfo->recrFunctions->end(); - iter++) { - iter->construct(iter->arg); - } - } -} - -/** - * Every thread should be marked as either TINFO_FLAG_NUWA_SUPPORT or - * TINFO_FLAG_NUWA_SKIP, or it means a potential error. We force - * Gecko code to mark every single thread to make sure there are no accidents - * when recreating threads with Nuwa. - * - * Threads marked as TINFO_FLAG_NUWA_SUPPORT can be checkpointed explicitly, by - * calling NuwaCheckpointCurrentThread(), or implicitly when they call into wrapped - * functions like pthread_mutex_lock(), epoll_wait(), etc. - * TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT denotes the explicitly checkpointed thread. - */ -#define TINFO_FLAG_NUWA_SUPPORT 0x1 -#define TINFO_FLAG_NUWA_SKIP 0x2 -#define TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT 0x4 - -static std::vector sConstructors; -static std::vector sFinalConstructors; - -class TLSKey -: public std::pair -, public LinkedListElement -{ -public: - TLSKey() {} - - TLSKey(pthread_key_t aKey, void (*aDestructor)(void*)) - : std::pair(aKey, aDestructor) - {} - - static void* operator new(size_t size) { - if (sUsed) - return ::operator new(size); - sUsed = true; - return sFirstElement.addr(); - } - - static void operator delete(void* ptr) { - if (ptr == sFirstElement.addr()) { - sUsed = false; - return; - } - ::operator delete(ptr); - } - -private: - static bool sUsed; - static AlignedStorage2 sFirstElement; -}; - -bool TLSKey::sUsed = false; -AlignedStorage2 TLSKey::sFirstElement; - -static AutoCleanLinkedList sTLSKeys; - -/** - * This mutex is used to block the running threads and freeze their contexts. - * PrepareNuwaProcess() is the first one to acquire the lock. Further attempts - * to acquire this mutex (in the freeze point macros) will block and freeze the - * calling thread. - */ -static pthread_mutex_t sThreadFreezeLock = PTHREAD_MUTEX_INITIALIZER; - -static thread_info_t sMainThread; -static int sThreadCount = 0; -static int sThreadFreezeCount = 0; - -// Bug 1008254: LinkedList's destructor asserts that the list is empty. -// But here, on exit, when the global sAllThreads list -// is destroyed, it may or may not be empty. Bug 1008254 comment 395 has a log -// when there were 8 threads remaining on exit. So this assertion was -// intermittently (almost every second time) failing. -// As a work-around to avoid this intermittent failure, we clear the list on -// exit just before it gets destroyed. This is the only purpose of that -// AllThreadsListType subclass. -struct AllThreadsListType : public AutoCleanLinkedList -{ - ~AllThreadsListType() - { - if (!isEmpty()) { - __android_log_print(ANDROID_LOG_WARN, "Nuwa", - "Threads remaining at exit:\n"); - int n = 0; - for (const thread_info_t* t = getFirst(); t; t = t->getNext()) { - __android_log_print(ANDROID_LOG_WARN, "Nuwa", - " %.*s (origNativeThreadID=%d recreatedNativeThreadID=%d)\n", - NATIVE_THREAD_NAME_LENGTH, - t->nativeThreadName, - t->origNativeThreadID, - t->recreatedNativeThreadID); - n++; - } - __android_log_print(ANDROID_LOG_WARN, "Nuwa", - "total: %d outstanding threads. " - "Please fix them so they're destroyed before this point!\n", n); - __android_log_print(ANDROID_LOG_WARN, "Nuwa", - "note: sThreadCount=%d, sThreadFreezeCount=%d\n", - sThreadCount, - sThreadFreezeCount); - } - } -}; -static AllThreadsListType sAllThreads; -static AllThreadsListType sExitingThreads; - -/** - * This mutex protects the access to thread info: - * sAllThreads, sThreadCount, sThreadFreezeCount, sRecreateVIPCount. - */ -static pthread_mutex_t sThreadCountLock = PTHREAD_MUTEX_INITIALIZER; -/** - * This condition variable lets MakeNuwaProcess() wait until all recreated - * threads are frozen. - */ -static pthread_cond_t sThreadChangeCond = PTHREAD_COND_INITIALIZER; - -/** - * This mutex and condition variable is used to serialize the fork requests - * from the parent process. - */ -static pthread_mutex_t sForkLock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t sForkWaitCond = PTHREAD_COND_INITIALIZER; - -/** - * sForkWaitCondChanged will be reset to false on the IPC thread before - * and will be changed to true on the main thread to indicate that the condition - * that the IPC thread is waiting for has already changed. - */ -static bool sForkWaitCondChanged = false; - -/** - * This mutex protects the access to sTLSKeys, which keeps track of existing - * TLS Keys. - */ -static pthread_mutex_t sTLSKeyLock = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER; -static int sThreadSkipCount = 0; - -static thread_info_t * -GetThreadInfoInner(pthread_t threadID) { - for (thread_info_t *tinfo = sAllThreads.getFirst(); - tinfo; - tinfo = tinfo->getNext()) { - if (pthread_equal(tinfo->origThreadID, threadID)) { - return tinfo; - } - } - - for (thread_info_t *tinfo = sExitingThreads.getFirst(); - tinfo; - tinfo = tinfo->getNext()) { - if (pthread_equal(tinfo->origThreadID, threadID)) { - return tinfo; - } - } - - return nullptr; -} - -/** - * Get thread info using the specified thread ID. - * - * @return thread_info_t which has threadID == specified threadID - */ -static thread_info_t * -GetThreadInfo(pthread_t threadID) { - REAL(pthread_mutex_lock)(&sThreadCountLock); - - thread_info_t *tinfo = GetThreadInfoInner(threadID); - - pthread_mutex_unlock(&sThreadCountLock); - return tinfo; -} - -#if !defined(HAVE_THREAD_TLS_KEYWORD) -/** - * Get thread info of the current thread. - * - * @return thread_info_t for the current thread. - */ -static thread_info_t * -GetCurThreadInfo() { - pthread_t threadID = REAL(pthread_self)(); - pthread_t thread_info_t::*threadIDptr = - (sIsNuwaProcess ? - &thread_info_t::origThreadID : - &thread_info_t::recreatedThreadID); - - REAL(pthread_mutex_lock)(&sThreadCountLock); - thread_info_t *tinfo; - for (tinfo = sAllThreads.getFirst(); - tinfo; - tinfo = tinfo->getNext()) { - if (pthread_equal(tinfo->*threadIDptr, threadID)) { - break; - } - } - pthread_mutex_unlock(&sThreadCountLock); - return tinfo; -} -#define CUR_THREAD_INFO GetCurThreadInfo() -#define SET_THREAD_INFO(x) /* Nothing to do. */ -#else -// Is not nullptr only for threads created by pthread_create() in an Nuwa process. -// It is always nullptr for the main thread. -static __thread thread_info_t *sCurThreadInfo = nullptr; -#define CUR_THREAD_INFO sCurThreadInfo -#define SET_THREAD_INFO(x) do { sCurThreadInfo = (x); } while(0) -#endif // HAVE_THREAD_TLS_KEYWORD - -/* - * Track all epoll fds and handling events. - */ -class EpollManager { -public: - class EpollInfo { - public: - typedef struct epoll_event Events; - typedef std::map EpollEventsMap; - typedef EpollEventsMap::iterator iterator; - typedef EpollEventsMap::const_iterator const_iterator; - - EpollInfo(): mBackSize(0) {} - EpollInfo(int aBackSize): mBackSize(aBackSize) {} - EpollInfo(const EpollInfo &aOther): mEvents(aOther.mEvents) - , mBackSize(aOther.mBackSize) { - } - ~EpollInfo() { - mEvents.clear(); - } - - void AddEvents(int aFd, Events &aEvents) { - std::pair pair = - mEvents.insert(std::make_pair(aFd, aEvents)); - if (!pair.second) { - abort(); - } - } - - void RemoveEvents(int aFd) { - if (!mEvents.erase(aFd)) { - abort(); - } - } - - void ModifyEvents(int aFd, Events &aEvents) { - iterator it = mEvents.find(aFd); - if (it == mEvents.end()) { - abort(); - } - it->second = aEvents; - } - - const Events &FindEvents(int aFd) const { - const_iterator it = mEvents.find(aFd); - if (it == mEvents.end()) { - abort(); - } - return it->second; - } - - int Size() const { return mEvents.size(); } - - // Iterator with values of pairs. - const_iterator begin() const { return mEvents.begin(); } - const_iterator end() const { return mEvents.end(); } - - int BackSize() const { return mBackSize; } - - private: - EpollEventsMap mEvents; - int mBackSize; - - friend class EpollManager; - }; - - typedef std::map EpollInfoMap; - typedef EpollInfoMap::iterator iterator; - typedef EpollInfoMap::const_iterator const_iterator; - -public: - void AddEpollInfo(int aEpollFd, int aBackSize) { - EpollInfo *oldinfo = FindEpollInfo(aEpollFd); - if (oldinfo != nullptr) { - abort(); - } - mEpollFdsInfo[aEpollFd] = EpollInfo(aBackSize); - } - - EpollInfo *FindEpollInfo(int aEpollFd) { - iterator it = mEpollFdsInfo.find(aEpollFd); - if (it == mEpollFdsInfo.end()) { - return nullptr; - } - return &it->second; - } - - void RemoveEpollInfo(int aEpollFd) { - if (!mEpollFdsInfo.erase(aEpollFd)) { - abort(); - } - } - - int Size() const { return mEpollFdsInfo.size(); } - - // Iterator of pairs. - const_iterator begin() const { return mEpollFdsInfo.begin(); } - const_iterator end() const { return mEpollFdsInfo.end(); } - - static EpollManager *Singleton() { - if (!sInstance) { - sInstance = new EpollManager(); - } - return sInstance; - } - - static void Shutdown() { - if (!sInstance) { - abort(); - } - - delete sInstance; - sInstance = nullptr; - } - -private: - static EpollManager *sInstance; - ~EpollManager() { - mEpollFdsInfo.clear(); - } - - EpollInfoMap mEpollFdsInfo; - - EpollManager() {} -}; - -EpollManager* EpollManager::sInstance; - -static thread_info_t * -thread_info_new(void) { - /* link tinfo to sAllThreads */ - thread_info_t *tinfo = new thread_info_t(); - tinfo->flags = 0; - tinfo->recrFunctions = nullptr; - tinfo->recreatedThreadID = 0; - tinfo->recreatedNativeThreadID = 0; - tinfo->condMutex = nullptr; - tinfo->condMutexNeedsBalancing = false; - - // Default stack and guard size. - tinfo->stackSize = NUWA_STACK_SIZE; - tinfo->guardSize = getPageSize(); - - REAL(pthread_mutex_lock)(&sThreadCountLock); - // Insert to the tail. - sAllThreads.insertBack(tinfo); - - sThreadCount++; - pthread_cond_signal(&sThreadChangeCond); - pthread_mutex_unlock(&sThreadCountLock); - - return tinfo; -} - -static void -thread_attr_init(thread_info_t *tinfo, const pthread_attr_t *tattr) -{ - pthread_attr_init(&tinfo->threadAttr); - - if (tattr) { - // Override default thread stack and guard size with tattr. - pthread_attr_getstacksize(tattr, &tinfo->stackSize); - pthread_attr_getguardsize(tattr, &tinfo->guardSize); - - size_t pageSize = getPageSize(); - - tinfo->stackSize = (tinfo->stackSize + pageSize - 1) % pageSize; - tinfo->guardSize = (tinfo->guardSize + pageSize - 1) % pageSize; - - int detachState = 0; - pthread_attr_getdetachstate(tattr, &detachState); - pthread_attr_setdetachstate(&tinfo->threadAttr, detachState); - } - - tinfo->stk = MozTaggedAnonymousMmap(nullptr, - tinfo->stackSize + tinfo->guardSize, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, - /* fd */ -1, - /* offset */ 0, - "nuwa-thread-stack"); - - // Add protection to stack overflow: mprotect() stack top (the page at the - // lowest address) so we crash instead of corrupt other content that is - // malloc()'d. - mprotect(tinfo->stk, tinfo->guardSize, PROT_NONE); - - pthread_attr_setstack(&tinfo->threadAttr, - (char*)tinfo->stk + tinfo->guardSize, - tinfo->stackSize); -} - -static void -thread_info_cleanup(void *arg) { - if (sNuwaForking) { - // We shouldn't have any thread exiting when we are forking a new process. - abort(); - } - - thread_info_t *tinfo = (thread_info_t *)arg; - pthread_attr_destroy(&tinfo->threadAttr); - - munmap(tinfo->stk, tinfo->stackSize + tinfo->guardSize); - - REAL(pthread_mutex_lock)(&sThreadCountLock); - /* unlink tinfo from sAllThreads */ - tinfo->remove(); - pthread_mutex_unlock(&sThreadCountLock); - - if (tinfo->recrFunctions) { - delete tinfo->recrFunctions; - } - - // while sThreadCountLock is held, since delete calls wrapped functions - // which try to lock sThreadCountLock. This results in deadlock. And we - // need to delete |tinfo| before decreasing sThreadCount, so Nuwa won't - // get ready before tinfo is cleaned. - delete tinfo; - - REAL(pthread_mutex_lock)(&sThreadCountLock); - sThreadCount--; - pthread_cond_signal(&sThreadChangeCond); - pthread_mutex_unlock(&sThreadCountLock); -} - -static void -EnsureThreadExited(thread_info_t *tinfo) { - pid_t thread = sIsNuwaProcess ? tinfo->origNativeThreadID - : tinfo->recreatedNativeThreadID; - // Wait until the target thread exits. Note that we use tgkill() instead of - // pthread_kill() because of: - // 1. Use after free inside pthread implementation. - // 2. Race due to pthread_t reuse when a thread is created. - while (!syscall(__NR_tgkill, getpid(), thread, 0)) { - sched_yield(); - } -} - -static void* -safe_thread_info_cleanup(void *arg) -{ - thread_info_t *tinfo = (thread_info_t *)arg; - - // We need to ensure the thread is really dead before cleaning up tinfo. - EnsureThreadExited(tinfo); - thread_info_cleanup(tinfo); - - return nullptr; -} - -static void -MaybeCleanUpDetachedThread(thread_info_t *tinfo) -{ - if (pthread_getattr_np(REAL(pthread_self()), &tinfo->threadAttr)) { - return; - } - - int detachState = 0; - if (pthread_attr_getdetachstate(&tinfo->threadAttr, &detachState) || - detachState == PTHREAD_CREATE_JOINABLE) { - // We only clean up tinfo of a detached thread. A joinable thread - // will be cleaned up in __wrap_pthread_join(). - return; - } - - // Create a detached thread to safely clean up the current thread. - pthread_t thread; - if (!REAL(pthread_create)(&thread, - nullptr, - safe_thread_info_cleanup, - tinfo)) { - pthread_detach(thread); - } -} - -static void -invalidate_thread_info(void *arg) { - REAL(pthread_mutex_lock)(&sThreadCountLock); - - // Unlink tinfo from sAllThreads to make it invisible from CUR_THREAD_INFO so - // it won't be misused by a newly created thread. - thread_info_t *tinfo = (thread_info_t*) arg; - tinfo->remove(); - sExitingThreads.insertBack(tinfo); - - pthread_mutex_unlock(&sThreadCountLock); - - MaybeCleanUpDetachedThread(tinfo); -} - -static void * -_thread_create_startup(void *arg) { - thread_info_t *tinfo = (thread_info_t *)arg; - void *r; - - // Save thread info; especially, stackaddr & stacksize. - // Reuse the stack in the new thread. - pthread_getattr_np(REAL(pthread_self)(), &tinfo->threadAttr); - - SET_THREAD_INFO(tinfo); - tinfo->origThreadID = REAL(pthread_self)(); - tinfo->origNativeThreadID = gettid(); - - r = tinfo->startupFunc(tinfo->startupArg); - - return r; -} - -// reserve STACK_RESERVED_SZ * 4 bytes for thread_recreate_startup(). -#define STACK_RESERVED_SZ 96 -#define STACK_SENTINEL(v) ((v)[0]) -#define STACK_SENTINEL_VALUE(v) ((uint32_t)(v) ^ 0xdeadbeef) - -static void * -thread_create_startup(void *arg) { - /* - * Dark Art!! Never try to do the same unless you are ABSOLUTELY sure of - * what you are doing! - * - * This function is here for reserving stack space before calling - * _thread_create_startup(). see also thread_create_startup(); - */ - void *r; - volatile uint32_t reserved[STACK_RESERVED_SZ]; - - // Reserve stack space. - STACK_SENTINEL(reserved) = STACK_SENTINEL_VALUE(reserved); - - r = _thread_create_startup(arg); - - // Check if the reservation is enough. - if (STACK_SENTINEL(reserved) != STACK_SENTINEL_VALUE(reserved)) { - abort(); // Did not reserve enough stack space. - } - - // Get tinfo before invalidating it. Note that we cannot use arg directly here - // because thread_recreate_startup() also runs on the same stack area and - // could corrupt the value. - thread_info_t *tinfo = CUR_THREAD_INFO; - invalidate_thread_info(tinfo); - - if (!sIsNuwaProcess) { - longjmp(tinfo->retEnv, 1); - - // Never go here! - abort(); - } - - return r; -} - -extern "C" MFBT_API int -__wrap_pthread_create(pthread_t *thread, - const pthread_attr_t *attr, - void *(*start_routine) (void *), - void *arg) { - if (!sIsNuwaProcess) { - return REAL(pthread_create)(thread, attr, start_routine, arg); - } - - thread_info_t *tinfo = thread_info_new(); - thread_attr_init(tinfo, attr); - tinfo->startupFunc = start_routine; - tinfo->startupArg = arg; - - int rv = REAL(pthread_create)(thread, - &tinfo->threadAttr, - thread_create_startup, - tinfo); - if (rv) { - thread_info_cleanup(tinfo); - } else { - tinfo->origThreadID = *thread; - } - - return rv; -} - -// TLS related - -/** - * Iterates over the existing TLS keys and store the TLS data for the current - * thread in tinfo. - */ -static void -SaveTLSInfo(thread_info_t *tinfo) { - MOZ_RELEASE_ASSERT(REAL(pthread_mutex_lock)(&sTLSKeyLock) == 0); - tinfo->tlsInfo.clear(); - for (TLSKey *it = sTLSKeys.getFirst(); it != nullptr; it = it->getNext()) { - void *value = pthread_getspecific(it->first); - if (value == nullptr) { - continue; - } - - pthread_key_t key = it->first; - tinfo->tlsInfo.push_back(TLSInfoList::value_type(key, value)); - } - MOZ_RELEASE_ASSERT(pthread_mutex_unlock(&sTLSKeyLock) == 0); -} - -/** - * Restores the TLS data for the current thread from tinfo. - */ -static void -RestoreTLSInfo(thread_info_t *tinfo) { - for (TLSInfoList::const_iterator it = tinfo->tlsInfo.begin(); - it != tinfo->tlsInfo.end(); - it++) { - pthread_key_t key = it->first; - const void *value = it->second; - if (pthread_setspecific(key, value)) { - abort(); - } - } - - SET_THREAD_INFO(tinfo); - tinfo->recreatedThreadID = REAL(pthread_self)(); - tinfo->recreatedNativeThreadID = gettid(); -} - -extern "C" MFBT_API int -__wrap_pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) { - int rv = REAL(pthread_key_create)(key, destructor); - if (rv != 0) { - return rv; - } - MOZ_RELEASE_ASSERT(REAL(pthread_mutex_lock)(&sTLSKeyLock) == 0); - sTLSKeys.insertBack(new TLSKey(*key, destructor)); - MOZ_RELEASE_ASSERT(pthread_mutex_unlock(&sTLSKeyLock) == 0); - return 0; -} - -extern "C" MFBT_API int -__wrap_pthread_key_delete(pthread_key_t key) { - // Don't call pthread_key_delete() for Nuwa-forked processes because bionic's - // pthread_key_delete() implementation can touch the thread stack that was - // freed in thread_info_cleanup(). - int rv = sIsNuwaChildProcess ? - 0 : REAL(pthread_key_delete)(key); - if (rv != 0) { - return rv; - } - MOZ_RELEASE_ASSERT(REAL(pthread_mutex_lock)(&sTLSKeyLock) == 0); - for (TLSKey *it = sTLSKeys.getFirst(); it != nullptr; it = it->getNext()) { - if (key == it->first) { - delete it; - break; - } - } - MOZ_RELEASE_ASSERT(pthread_mutex_unlock(&sTLSKeyLock) == 0); - return 0; -} - -extern "C" MFBT_API pthread_t -__wrap_pthread_self() { - thread_info_t *tinfo = CUR_THREAD_INFO; - if (tinfo) { - // For recreated thread, masquerade as the original thread in the Nuwa - // process. - return tinfo->origThreadID; - } - return REAL(pthread_self)(); -} - -extern "C" MFBT_API int -__wrap_pthread_join(pthread_t thread, void **retval) { - thread_info_t *tinfo = GetThreadInfo(thread); - if (tinfo == nullptr) { - return REAL(pthread_join)(thread, retval); - } - - pthread_t thread_info_t::*threadIDptr = - (sIsNuwaProcess ? - &thread_info_t::origThreadID : - &thread_info_t::recreatedThreadID); - - // pthread_join() uses the origThreadID or recreatedThreadID depending on - // whether we are in Nuwa or forked processes. - int rc = REAL(pthread_join)(tinfo->*threadIDptr, retval); - - // Before Android L, bionic wakes up the caller of pthread_join() with - // pthread_cond_signal() so the thread can still use the stack for some while. - // Call safe_thread_info_cleanup() to destroy tinfo after the thread really - // exits. - safe_thread_info_cleanup(tinfo); - - return rc; -} - -/** - * The following are used to synchronize between the main thread and the - * thread being recreated. The main thread will wait until the thread is woken - * up from the freeze points or the blocking intercepted functions and then - * proceed to recreate the next frozen thread. - * - * In thread recreation, the main thread recreates the frozen threads one by - * one. The recreated threads will be "gated" until the main thread "opens the - * gate" to let them run freely as if they were created from scratch. The VIP - * threads gets the chance to run first after their thread stacks are recreated - * (using longjmp()) so they can adjust their contexts to a valid, consistent - * state. The threads frozen waiting for pthread condition variables are VIP - * threads. After woken up they need to run first to make the associated mutex - * in a valid state to maintain the semantics of the intercepted function calls - * (like pthread_cond_wait()). - */ - -// Used to synchronize the main thread and the thread being recreated so that -// only one thread is allowed to be recreated at a time. -static pthread_mutex_t sRecreateWaitLock = PTHREAD_MUTEX_INITIALIZER; -// Used to block recreated threads until the main thread "opens the gate". -static pthread_mutex_t sRecreateGateLock = PTHREAD_MUTEX_INITIALIZER; -// Used to block the main thread from "opening the gate" until all VIP threads -// have been recreated. -static pthread_mutex_t sRecreateVIPGateLock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t sRecreateVIPCond = PTHREAD_COND_INITIALIZER; -static int sRecreateVIPCount = 0; -static int sRecreateGatePassed = 0; - -/** - * Thread recreation macros. - * - * The following macros are used in the forked process to synchronize and - * control the progress of thread recreation. - * - * 1. RECREATE_START() is first called in the beginning of thread - * recreation to set sRecreateWaitLock and sRecreateGateLock in locked - * state. - * 2. For each frozen thread: - * 2.1. RECREATE_BEFORE() to set the thread being recreated. - * 2.2. thread_recreate() to recreate the frozen thread. - * 2.3. Main thread calls RECREATE_WAIT() to wait on sRecreateWaitLock until - * the thread is recreated from the freeze point and calls - * RECREATE_CONTINUE() to release sRecreateWaitLock. - * 2.3. Non-VIP threads are blocked on RECREATE_GATE(). VIP threads calls - * RECREATE_PASS_VIP() to mark that a VIP thread is successfully - * recreated and then is blocked by calling RECREATE_GATE_VIP(). - * 3. RECREATE_WAIT_ALL_VIP() to wait until all VIP threads passed, that is, - * VIP threads already has their contexts (mainly pthread mutex) in a valid - * state. - * 4. RECREATE_OPEN_GATE() to unblock threads blocked by sRecreateGateLock. - * 5. RECREATE_FINISH() to complete thread recreation. - */ -#define RECREATE_START() \ - do { \ - REAL(pthread_mutex_lock)(&sRecreateWaitLock); \ - REAL(pthread_mutex_lock)(&sRecreateGateLock); \ - } while(0) -#define RECREATE_BEFORE(info) do { sCurrentRecreatingThread = info; } while(0) -#define RECREATE_WAIT() REAL(pthread_mutex_lock)(&sRecreateWaitLock) -#define RECREATE_CONTINUE() do { \ - RunCustomRecreation(); \ - pthread_mutex_unlock(&sRecreateWaitLock); \ - } while(0) -#define RECREATE_FINISH() pthread_mutex_unlock(&sRecreateWaitLock) -#define RECREATE_GATE() \ - do { \ - REAL(pthread_mutex_lock)(&sRecreateGateLock); \ - sRecreateGatePassed++; \ - pthread_mutex_unlock(&sRecreateGateLock); \ - } while(0) -#define RECREATE_OPEN_GATE() pthread_mutex_unlock(&sRecreateGateLock) -#define RECREATE_GATE_VIP() \ - do { \ - REAL(pthread_mutex_lock)(&sRecreateGateLock); \ - pthread_mutex_unlock(&sRecreateGateLock); \ - } while(0) -#define RECREATE_PASS_VIP() \ - do { \ - REAL(pthread_mutex_lock)(&sRecreateVIPGateLock); \ - sRecreateGatePassed++; \ - pthread_cond_signal(&sRecreateVIPCond); \ - pthread_mutex_unlock(&sRecreateVIPGateLock); \ - } while(0) -#define RECREATE_WAIT_ALL_VIP() \ - do { \ - REAL(pthread_mutex_lock)(&sRecreateVIPGateLock); \ - while(sRecreateGatePassed < sRecreateVIPCount) { \ - REAL(pthread_cond_wait)(&sRecreateVIPCond, \ - &sRecreateVIPGateLock); \ - } \ - pthread_mutex_unlock(&sRecreateVIPGateLock); \ - } while(0) - -/** - * Thread freeze points. Note that the freeze points are implemented as macros - * so as not to garble the content of the stack after setjmp(). - * - * In the nuwa process, when a thread supporting nuwa calls a wrapper - * function, freeze point 1 setjmp()s to save the state. We only allow the - * thread to be frozen in the wrapper functions. If thread freezing is not - * enabled yet, the wrapper functions act like their wrapped counterparts, - * except for the extra actions in the freeze points. If thread freezing is - * enabled, the thread will be frozen by calling one of the wrapper functions. - * The threads can be frozen in any of the following points: - * - * 1) Freeze point 1: this is the point where we setjmp() in the nuwa process - * and longjmp() in the spawned process. If freezing is enabled, then the - * current thread blocks by acquiring an already locked mutex, - * sThreadFreezeLock. - * 2) The wrapped function: the function that might block waiting for some - * resource or condition. - * 3) Freeze point 2: blocks the current thread by acquiring sThreadFreezeLock. - * If freezing is not enabled then revert the counter change in freeze - * point 1. - * - * Note: the purpose of the '(void) variable;' statements is to avoid - * -Wunused-but-set-variable warnings. - */ -#define THREAD_FREEZE_POINT1() \ - bool freezeCountChg = false; \ - bool recreated = false; \ - (void) recreated; \ - volatile bool freezePoint2 = false; \ - (void) freezePoint2; \ - thread_info_t *tinfo; \ - if (sIsNuwaProcess && \ - (tinfo = CUR_THREAD_INFO) && \ - (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) && \ - !(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) { \ - if (!setjmp(tinfo->jmpEnv)) { \ - REAL(pthread_mutex_lock)(&sThreadCountLock); \ - SaveTLSInfo(tinfo); \ - sThreadFreezeCount++; \ - freezeCountChg = true; \ - pthread_cond_signal(&sThreadChangeCond); \ - pthread_mutex_unlock(&sThreadCountLock); \ - \ - if (sIsFreezing) { \ - REAL(pthread_mutex_lock)(&sThreadFreezeLock); \ - /* Never return from the pthread_mutex_lock() call. */ \ - abort(); \ - } \ - } else { \ - POST_SETJMP_RESTORE("THREAD_FREEZE_POINT1"); \ - RECREATE_CONTINUE(); \ - RECREATE_GATE(); \ - freezeCountChg = false; \ - recreated = true; \ - } \ - } - -#define THREAD_FREEZE_POINT1_VIP() \ - bool freezeCountChg = false; \ - bool recreated = false; \ - volatile bool freezePoint1 = false; \ - volatile bool freezePoint2 = false; \ - thread_info_t *tinfo; \ - if (sIsNuwaProcess && \ - (tinfo = CUR_THREAD_INFO) && \ - (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) && \ - !(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) { \ - if (!setjmp(tinfo->jmpEnv)) { \ - REAL(pthread_mutex_lock)(&sThreadCountLock); \ - SaveTLSInfo(tinfo); \ - sThreadFreezeCount++; \ - sRecreateVIPCount++; \ - freezeCountChg = true; \ - pthread_cond_signal(&sThreadChangeCond); \ - pthread_mutex_unlock(&sThreadCountLock); \ - \ - if (sIsFreezing) { \ - freezePoint1 = true; \ - REAL(pthread_mutex_lock)(&sThreadFreezeLock); \ - /* Never return from the pthread_mutex_lock() call. */ \ - abort(); \ - } \ - } else { \ - POST_SETJMP_RESTORE("THREAD_FREEZE_POINT1_VIP"); \ - freezeCountChg = false; \ - recreated = true; \ - } \ - } - -#define THREAD_FREEZE_POINT2() \ - if (freezeCountChg) { \ - REAL(pthread_mutex_lock)(&sThreadCountLock); \ - if (sNuwaReady && sIsNuwaProcess) { \ - pthread_mutex_unlock(&sThreadCountLock); \ - freezePoint2 = true; \ - REAL(pthread_mutex_lock)(&sThreadFreezeLock); \ - /* Never return from the pthread_mutex_lock() call. */ \ - abort(); \ - } \ - sThreadFreezeCount--; \ - pthread_cond_signal(&sThreadChangeCond); \ - pthread_mutex_unlock(&sThreadCountLock); \ - } - -#define THREAD_FREEZE_POINT2_VIP() \ - if (freezeCountChg) { \ - REAL(pthread_mutex_lock)(&sThreadCountLock); \ - if (sNuwaReady && sIsNuwaProcess) { \ - pthread_mutex_unlock(&sThreadCountLock); \ - freezePoint2 = true; \ - REAL(pthread_mutex_lock)(&sThreadFreezeLock); \ - /* Never return from the pthread_mutex_lock() call. */ \ - abort(); \ - } \ - sThreadFreezeCount--; \ - sRecreateVIPCount--; \ - pthread_cond_signal(&sThreadChangeCond); \ - pthread_mutex_unlock(&sThreadCountLock); \ - } - -/** - * Wrapping the blocking functions: epoll_wait(), poll(), pthread_mutex_lock(), - * pthread_cond_wait() and pthread_cond_timedwait(): - * - * These functions are wrapped by the above freeze point macros. Once a new - * process is forked, the recreated thread will be blocked in one of the wrapper - * functions. When recreating the thread, we longjmp() to - * THREAD_FREEZE_POINT1() to recover the thread stack. Care must be taken to - * maintain the semantics of the wrapped function: - * - * - epoll_wait() and poll(): just retry the function. - * - pthread_mutex_lock(): don't lock if frozen at freeze point 2 (lock is - * already acquired). - * - pthread_cond_wait() and pthread_cond_timedwait(): if the thread is frozen - * waiting the condition variable, the mutex is already released, we need to - * reacquire the mutex before calling the wrapped function again so the mutex - * will be in a valid state. - */ - -extern "C" MFBT_API int -__wrap_epoll_wait(int epfd, - struct epoll_event *events, - int maxevents, - int timeout) { - int rv; - - THREAD_FREEZE_POINT1(); - rv = REAL(epoll_wait)(epfd, events, maxevents, timeout); - THREAD_FREEZE_POINT2(); - - return rv; -} - -extern "C" MFBT_API int -__wrap_pthread_cond_wait(pthread_cond_t *cond, - pthread_mutex_t *mtx) { - int rv = 0; - - THREAD_FREEZE_POINT1_VIP(); - if (freezePoint2) { - RECREATE_CONTINUE(); - RECREATE_PASS_VIP(); - RECREATE_GATE_VIP(); - return rv; - } - if (recreated && mtx) { - if (!freezePoint1) { - tinfo->condMutex = mtx; - // The thread was frozen in pthread_cond_wait() after releasing mtx in the - // Nuwa process. In recreating this thread, We failed to reacquire mtx - // with the pthread_mutex_trylock() call, that is, mtx was acquired by - // another thread. Because of this, we need the main thread's help to - // reacquire mtx so that it will be in a valid state. - if (!pthread_mutex_trylock(mtx)) { - tinfo->condMutexNeedsBalancing = true; - } - } - RECREATE_CONTINUE(); - RECREATE_PASS_VIP(); - } - rv = REAL(pthread_cond_wait)(cond, mtx); - if (recreated && mtx) { - // We have reacquired mtx. The main thread also wants to acquire mtx to - // synchronize with us. If the main thread didn't get a chance to acquire - // mtx let it do that now. The main thread clears condMutex after acquiring - // it to signal us. - if (tinfo->condMutex) { - // We need mtx to end up locked, so tell the main thread not to unlock - // mtx after it locks it. - tinfo->condMutexNeedsBalancing = false; - pthread_mutex_unlock(mtx); - } - // We still need to be gated as not to acquire another mutex associated with - // another VIP thread and interfere with it. - RECREATE_GATE_VIP(); - } - THREAD_FREEZE_POINT2_VIP(); - - return rv; -} - -extern "C" MFBT_API int -__wrap_pthread_cond_timedwait(pthread_cond_t *cond, - pthread_mutex_t *mtx, - const struct timespec *abstime) { - int rv = 0; - - THREAD_FREEZE_POINT1_VIP(); - if (freezePoint2) { - RECREATE_CONTINUE(); - RECREATE_PASS_VIP(); - RECREATE_GATE_VIP(); - return rv; - } - if (recreated && mtx) { - if (!freezePoint1) { - tinfo->condMutex = mtx; - if (!pthread_mutex_trylock(mtx)) { - tinfo->condMutexNeedsBalancing = true; - } - } - RECREATE_CONTINUE(); - RECREATE_PASS_VIP(); - } - rv = REAL(pthread_cond_timedwait)(cond, mtx, abstime); - if (recreated && mtx) { - if (tinfo->condMutex) { - tinfo->condMutexNeedsBalancing = false; - pthread_mutex_unlock(mtx); - } - RECREATE_GATE_VIP(); - } - THREAD_FREEZE_POINT2_VIP(); - - return rv; -} - - -extern "C" MFBT_API int -__wrap_pthread_mutex_trylock(pthread_mutex_t *mtx) { - int rv = 0; - - THREAD_FREEZE_POINT1(); - if (freezePoint2) { - return rv; - } - rv = REAL(pthread_mutex_trylock)(mtx); - THREAD_FREEZE_POINT2(); - - return rv; -} - -extern "C" MFBT_API int -__wrap_pthread_mutex_lock(pthread_mutex_t *mtx) { - int rv = 0; - - THREAD_FREEZE_POINT1(); - if (freezePoint2) { - return rv; - } - rv = REAL(pthread_mutex_lock)(mtx); - THREAD_FREEZE_POINT2(); - - return rv; -} - -extern "C" MFBT_API int -__wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout) { - int rv; - - THREAD_FREEZE_POINT1(); - rv = REAL(poll)(fds, nfds, timeout); - THREAD_FREEZE_POINT2(); - - return rv; -} - -extern "C" MFBT_API int -__wrap_epoll_create(int size) { - int epollfd = REAL(epoll_create)(size); - - if (!sIsNuwaProcess) { - return epollfd; - } - - if (epollfd >= 0) { - EpollManager::Singleton()->AddEpollInfo(epollfd, size); - } - - return epollfd; -} - -/** - * Wrapping the functions to create file descriptor pairs. In the child process - * FD pairs are created for intra-process signaling. The generation of FD pairs - * need to be tracked in the nuwa process so they can be recreated in the - * spawned process. - */ -struct FdPairInfo { - enum { - kPipe, - kSocketpair - } call; - - int FDs[2]; - int flags; - int domain; - int type; - int protocol; -}; - -/** - * Protects the access to sSingalFds. - */ -static pthread_mutex_t sSignalFdLock = PTHREAD_MUTEX_INITIALIZER; -static std::vector sSignalFds; - -extern "C" MFBT_API int -__wrap_socketpair(int domain, int type, int protocol, int sv[2]) -{ - int rv = REAL(socketpair)(domain, type, protocol, sv); - - if (!sIsNuwaProcess || rv < 0) { - return rv; - } - - REAL(pthread_mutex_lock)(&sSignalFdLock); - FdPairInfo signalFd; - signalFd.call = FdPairInfo::kSocketpair; - signalFd.FDs[0] = sv[0]; - signalFd.FDs[1] = sv[1]; - signalFd.domain = domain; - signalFd.type = type; - signalFd.protocol = protocol; - - sSignalFds.push_back(signalFd); - pthread_mutex_unlock(&sSignalFdLock); - - return rv; -} - -extern "C" MFBT_API int -__wrap_pipe2(int __pipedes[2], int flags) -{ - int rv = REAL(pipe2)(__pipedes, flags); - if (!sIsNuwaProcess || rv < 0) { - return rv; - } - - REAL(pthread_mutex_lock)(&sSignalFdLock); - FdPairInfo signalFd; - signalFd.call = FdPairInfo::kPipe; - signalFd.FDs[0] = __pipedes[0]; - signalFd.FDs[1] = __pipedes[1]; - signalFd.flags = flags; - sSignalFds.push_back(signalFd); - pthread_mutex_unlock(&sSignalFdLock); - return rv; -} - -extern "C" MFBT_API int -__wrap_pipe(int __pipedes[2]) -{ - return __wrap_pipe2(__pipedes, 0); -} - -static void -DupeSingleFd(int newFd, int origFd) -{ - struct stat sb; - if (fstat(origFd, &sb)) { - // Maybe the original FD is closed. - return; - } - int fd = fcntl(origFd, F_GETFD); - int fl = fcntl(origFd, F_GETFL); - dup2(newFd, origFd); - fcntl(origFd, F_SETFD, fd); - fcntl(origFd, F_SETFL, fl); - REAL(close)(newFd); -} - -extern "C" MFBT_API void -ReplaceSignalFds() -{ - for (std::vector::iterator it = sSignalFds.begin(); - it < sSignalFds.end(); ++it) { - int fds[2]; - int rc = 0; - switch (it->call) { - case FdPairInfo::kPipe: - rc = REAL(pipe2)(fds, it->flags); - break; - case FdPairInfo::kSocketpair: - rc = REAL(socketpair)(it->domain, it->type, it->protocol, fds); - break; - default: - continue; - } - - if (rc == 0) { - DupeSingleFd(fds[0], it->FDs[0]); - DupeSingleFd(fds[1], it->FDs[1]); - } - } -} - -extern "C" MFBT_API int -__wrap_epoll_ctl(int aEpollFd, int aOp, int aFd, struct epoll_event *aEvent) { - int rv = REAL(epoll_ctl)(aEpollFd, aOp, aFd, aEvent); - - if (!sIsNuwaProcess || rv == -1) { - return rv; - } - - EpollManager::EpollInfo *info = - EpollManager::Singleton()->FindEpollInfo(aEpollFd); - if (info == nullptr) { - abort(); - } - - switch(aOp) { - case EPOLL_CTL_ADD: - info->AddEvents(aFd, *aEvent); - break; - - case EPOLL_CTL_MOD: - info->ModifyEvents(aFd, *aEvent); - break; - - case EPOLL_CTL_DEL: - info->RemoveEvents(aFd); - break; - - default: - abort(); - } - - return rv; -} - -// XXX: thinker: Maybe, we should also track dup, dup2, and other functions. -extern "C" MFBT_API int -__wrap_close(int aFd) { - int rv = REAL(close)(aFd); - if (!sIsNuwaProcess || rv == -1) { - return rv; - } - - EpollManager::EpollInfo *info = - EpollManager::Singleton()->FindEpollInfo(aFd); - if (info) { - EpollManager::Singleton()->RemoveEpollInfo(aFd); - } - - return rv; -} - -static void * -thread_recreate_startup(void *arg) { - /* - * Dark Art!! Never do the same unless you are ABSOLUTELY sure what you are - * doing! - * - * The stack space collapsed by this frame had been reserved by - * thread_create_startup(). And thread_create_startup() will - * return immediately after returning from real start routine, so - * all collapsed values does not affect the result. - * - * All outer frames of thread_create_startup() and - * thread_recreate_startup() are equivalent, so - * thread_create_startup() will return successfully. - */ - thread_info_t *tinfo = (thread_info_t *)arg; - - prctl(PR_SET_NAME, (unsigned long)&tinfo->nativeThreadName, 0, 0, 0); - RestoreTLSInfo(tinfo); - - if (setjmp(tinfo->retEnv) != 0) { - POST_SETJMP_RESTORE("thread_recreate_startup"); - return nullptr; - } - - // longjump() to recreate the stack on the new thread. - longjmp(tinfo->jmpEnv, 1); - - // Never go here! - abort(); - - return nullptr; -} - -/** - * Recreate the context given by tinfo at a new thread. - */ -static void -thread_recreate(thread_info_t *tinfo) { - pthread_t thread; - - // Note that the thread_recreate_startup() runs on the stack specified by - // tinfo. - pthread_create(&thread, &tinfo->threadAttr, thread_recreate_startup, tinfo); -} - -/** - * Recreate all threads in a process forked from an Nuwa process. - */ -static void -RecreateThreads() { - sIsNuwaProcess = false; - sIsFreezing = false; - - sMainThread.recreatedThreadID = pthread_self(); - sMainThread.recreatedNativeThreadID = gettid(); - - // Run registered constructors. - for (std::vector::iterator ctr = sConstructors.begin(); - ctr != sConstructors.end(); - ctr++) { - (*ctr).construct((*ctr).arg); - } - sConstructors.clear(); - - REAL(pthread_mutex_lock)(&sThreadCountLock); - thread_info_t *tinfo = sAllThreads.getFirst(); - pthread_mutex_unlock(&sThreadCountLock); - - RECREATE_START(); - while (tinfo != nullptr) { - if (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) { - RECREATE_BEFORE(tinfo); - thread_recreate(tinfo); - RECREATE_WAIT(); - if (tinfo->condMutex) { - // Synchronize with the recreated thread in pthread_cond_wait(). - REAL(pthread_mutex_lock)(tinfo->condMutex); - // Tell the other thread that we have successfully locked the mutex. - // NB: condMutex can only be touched while it is held, so we must clear - // it here and store the mutex locally. - pthread_mutex_t *mtx = tinfo->condMutex; - tinfo->condMutex = nullptr; - if (tinfo->condMutexNeedsBalancing) { - pthread_mutex_unlock(mtx); - } - } - } else if(!(tinfo->flags & TINFO_FLAG_NUWA_SKIP)) { - // An unmarked thread is found other than the main thread. - - // All threads should be marked as one of SUPPORT or SKIP, or - // abort the process to make sure all threads in the Nuwa - // process are Nuwa-aware. - abort(); - } - - tinfo = tinfo->getNext(); - } - RECREATE_WAIT_ALL_VIP(); - RECREATE_OPEN_GATE(); - - RECREATE_FINISH(); - - // Run registered final constructors. - for (std::vector::iterator ctr = sFinalConstructors.begin(); - ctr != sFinalConstructors.end(); - ctr++) { - (*ctr).construct((*ctr).arg); - } - sFinalConstructors.clear(); -} - -extern "C" { - -/** - * Recreate all epoll fds and restore status; include all events. - */ -static void -RecreateEpollFds() { - EpollManager *man = EpollManager::Singleton(); - - for (EpollManager::const_iterator info_it = man->begin(); - info_it != man->end(); - info_it++) { - int epollfd = info_it->first; - const EpollManager::EpollInfo *info = &info_it->second; - - int fdflags = fcntl(epollfd, F_GETFD); - if (fdflags == -1) { - abort(); - } - int fl = fcntl(epollfd, F_GETFL); - if (fl == -1) { - abort(); - } - - int newepollfd = REAL(epoll_create)(info->BackSize()); - if (newepollfd == -1) { - abort(); - } - int rv = REAL(close)(epollfd); - if (rv == -1) { - abort(); - } - rv = dup2(newepollfd, epollfd); - if (rv == -1) { - abort(); - } - rv = REAL(close)(newepollfd); - if (rv == -1) { - abort(); - } - - rv = fcntl(epollfd, F_SETFD, fdflags); - if (rv == -1) { - abort(); - } - rv = fcntl(epollfd, F_SETFL, fl); - if (rv == -1) { - abort(); - } - - for (EpollManager::EpollInfo::const_iterator events_it = info->begin(); - events_it != info->end(); - events_it++) { - int fd = events_it->first; - epoll_event events; - events = events_it->second; - rv = REAL(epoll_ctl)(epollfd, EPOLL_CTL_ADD, fd, &events); - if (rv == -1) { - abort(); - } - } - } - - // Shutdown EpollManager. It won't be needed in the spawned process. - EpollManager::Shutdown(); -} - -/** - * Fix IPC to make it ready. - * - * Especially, fix ContentChild. - */ -static void -ReplaceIPC(NuwaProtoFdInfo *aInfoList, int aInfoSize) { - int i; - int rv; - - for (i = 0; i < aInfoSize; i++) { - int fd = fcntl(aInfoList[i].originFd, F_GETFD); - if (fd == -1) { - abort(); - } - - int fl = fcntl(aInfoList[i].originFd, F_GETFL); - if (fl == -1) { - abort(); - } - - rv = dup2(aInfoList[i].newFds[NUWA_NEWFD_CHILD], aInfoList[i].originFd); - if (rv == -1) { - abort(); - } - - rv = fcntl(aInfoList[i].originFd, F_SETFD, fd); - if (rv == -1) { - abort(); - } - - rv = fcntl(aInfoList[i].originFd, F_SETFL, fl); - if (rv == -1) { - abort(); - } - } -} - -/** - * Add a new content process at the chrome process. - */ -static void -AddNewProcess(pid_t pid, NuwaProtoFdInfo *aInfoList, int aInfoSize) { - static bool (*AddNewIPCProcess)(pid_t, NuwaProtoFdInfo *, int) = nullptr; - - if (AddNewIPCProcess == nullptr) { - AddNewIPCProcess = (bool (*)(pid_t, NuwaProtoFdInfo *, int)) - dlsym(RTLD_DEFAULT, "AddNewIPCProcess"); - } - AddNewIPCProcess(pid, aInfoList, aInfoSize); -} - -static void -PrepareProtoSockets(NuwaProtoFdInfo *aInfoList, int aInfoSize) { - int i; - int rv; - - for (i = 0; i < aInfoSize; i++) { - rv = REAL(socketpair)(PF_UNIX, SOCK_STREAM, 0, aInfoList[i].newFds); - if (rv == -1) { - abort(); - } - } -} - -static void -CloseAllProtoSockets(NuwaProtoFdInfo *aInfoList, int aInfoSize) { - int i; - - for (i = 0; i < aInfoSize; i++) { - REAL(close)(aInfoList[i].newFds[0]); - REAL(close)(aInfoList[i].newFds[1]); - } -} - -static void -AfterForkHook() -{ - void (*AfterNuwaFork)(); - - // This is defined in dom/ipc/ContentChild.cpp - AfterNuwaFork = (void (*)()) - dlsym(RTLD_DEFAULT, "AfterNuwaFork"); - AfterNuwaFork(); -} - -/** - * Fork a new process that is ready for running IPC. - * - * @return the PID of the new process. - */ -static int -ForkIPCProcess() { - int pid; - - REAL(pthread_mutex_lock)(&sForkLock); - - PrepareProtoSockets(sProtoFdInfos, sProtoFdInfosSize); - - sNuwaForking = true; - pid = fork(); - sNuwaForking = false; - if (pid == -1) { - abort(); - } - - if (pid > 0) { - // in the parent - AddNewProcess(pid, sProtoFdInfos, sProtoFdInfosSize); - CloseAllProtoSockets(sProtoFdInfos, sProtoFdInfosSize); - } else { - // in the child - sIsNuwaChildProcess = true; - if (getenv("MOZ_DEBUG_CHILD_PROCESS")) { - printf("\n\nNUWA CHILDCHILDCHILDCHILD\n debug me @ %d\n\n", getpid()); - sleep(30); - } - AfterForkHook(); - ReplaceSignalFds(); - ReplaceIPC(sProtoFdInfos, sProtoFdInfosSize); - RecreateEpollFds(); - RecreateThreads(); - CloseAllProtoSockets(sProtoFdInfos, sProtoFdInfosSize); - } - - sForkWaitCondChanged = true; - pthread_cond_signal(&sForkWaitCond); - pthread_mutex_unlock(&sForkLock); - - return pid; -} - -/** - * Prepare for spawning a new process. Called on the IPC thread. - */ -MFBT_API void -NuwaSpawnPrepare() { - REAL(pthread_mutex_lock)(&sForkLock); - - sForkWaitCondChanged = false; // Will be modified on the main thread. -} - -/** - * Let IPC thread wait until fork action on the main thread has completed. - */ -MFBT_API void -NuwaSpawnWait() { - while (!sForkWaitCondChanged) { - REAL(pthread_cond_wait)(&sForkWaitCond, &sForkLock); - } - pthread_mutex_unlock(&sForkLock); -} - -/** - * Spawn a new process. If not ready for spawn (still waiting for some threads - * to freeze), postpone the spawn request until ready. - * - * @return the pid of the new process, or 0 if not ready. - */ -MFBT_API pid_t -NuwaSpawn() { - if (gettid() != getpid()) { - // Not the main thread. - abort(); - } - - pid_t pid = 0; - - if (sNuwaReady) { - pid = ForkIPCProcess(); - } else { - sNuwaPendingSpawn = true; - } - - return pid; -} - -/** - * Prepare to freeze the Nuwa-supporting threads. - */ -MFBT_API void -PrepareNuwaProcess() { - sIsNuwaProcess = true; - // Explicitly ignore SIGCHLD so we don't have to call watpid() to reap - // dead child processes. - signal(SIGCHLD, SIG_IGN); - - // Make marked threads block in one freeze point. - REAL(pthread_mutex_lock)(&sThreadFreezeLock); - - // Populate sMainThread for mapping of tgkill. - sMainThread.origThreadID = pthread_self(); - sMainThread.origNativeThreadID = gettid(); -} - -// Make current process as a Nuwa process. -MFBT_API void -MakeNuwaProcess() { - void (*GetProtoFdInfos)(NuwaProtoFdInfo *, int, int *) = nullptr; - void (*OnNuwaProcessReady)() = nullptr; - sIsFreezing = true; - - REAL(pthread_mutex_lock)(&sThreadCountLock); - - // wait until all threads are frozen. - while ((sThreadFreezeCount + sThreadSkipCount) != sThreadCount) { - REAL(pthread_cond_wait)(&sThreadChangeCond, &sThreadCountLock); - } - - GetProtoFdInfos = (void (*)(NuwaProtoFdInfo *, int, int *)) - dlsym(RTLD_DEFAULT, "GetProtoFdInfos"); - GetProtoFdInfos(sProtoFdInfos, NUWA_TOPLEVEL_MAX, &sProtoFdInfosSize); - - sNuwaReady = true; - - pthread_mutex_unlock(&sThreadCountLock); - - OnNuwaProcessReady = (void (*)())dlsym(RTLD_DEFAULT, "OnNuwaProcessReady"); - OnNuwaProcessReady(); - - if (sNuwaPendingSpawn) { - sNuwaPendingSpawn = false; - NuwaSpawn(); - } -} - -/** - * Mark the current thread as supporting Nuwa. The thread will be recreated in - * the spawned process. - */ -MFBT_API void -NuwaMarkCurrentThread(void (*recreate)(void *), void *arg) { - if (!sIsNuwaProcess) { - return; - } - - thread_info_t *tinfo = CUR_THREAD_INFO; - if (tinfo == nullptr) { - abort(); - } - - tinfo->flags |= TINFO_FLAG_NUWA_SUPPORT; - if (recreate) { - nuwa_construct_t construct(recreate, arg); - tinfo->addThreadConstructor(&construct); - } - - // XXX Thread name might be set later than this call. If this is the case, we - // might need to delay getting the thread name. - prctl(PR_GET_NAME, (unsigned long)&tinfo->nativeThreadName, 0, 0, 0); -} - -/** - * Mark the current thread as not supporting Nuwa. Don't recreate this thread in - * the spawned process. - */ -MFBT_API void -NuwaSkipCurrentThread() { - if (!sIsNuwaProcess) return; - - thread_info_t *tinfo = CUR_THREAD_INFO; - if (tinfo == nullptr) { - abort(); - } - - if (!(tinfo->flags & TINFO_FLAG_NUWA_SKIP)) { - sThreadSkipCount++; - } - tinfo->flags |= TINFO_FLAG_NUWA_SKIP; -} - -/** - * Force to freeze the current thread. - * - * This method does not return in Nuwa process. It returns for the - * recreated thread. - */ -MFBT_API void -NuwaFreezeCurrentThread() { - thread_info_t *tinfo = CUR_THREAD_INFO; - if (sIsNuwaProcess && - (tinfo = CUR_THREAD_INFO) && - (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT)) { - if (!setjmp(tinfo->jmpEnv)) { - REAL(pthread_mutex_lock)(&sThreadCountLock); - SaveTLSInfo(tinfo); - sThreadFreezeCount++; - pthread_cond_signal(&sThreadChangeCond); - pthread_mutex_unlock(&sThreadCountLock); - - REAL(pthread_mutex_lock)(&sThreadFreezeLock); - } else { - POST_SETJMP_RESTORE("NuwaFreezeCurrentThread"); - RECREATE_CONTINUE(); - RECREATE_GATE(); - } - } -} - -/** - * The caller of NuwaCheckpointCurrentThread() is at the line it wishes to - * return after the thread is recreated. - * - * The checkpointed thread will restart at the calling line of - * NuwaCheckpointCurrentThread(). This macro returns true in the Nuwa process - * and false on the recreated thread in the forked process. - * - * NuwaCheckpointCurrentThread() is implemented as a macro so we can place the - * setjmp() call in the calling method without changing its stack pointer. This - * is essential for not corrupting the stack when the calling thread continues - * to request the main thread for forking a new process. The caller of - * NuwaCheckpointCurrentThread() should not return before the process forking - * finishes. - * - * @return true for Nuwa process, and false in the forked process. - */ -MFBT_API jmp_buf* -NuwaCheckpointCurrentThread1() { - thread_info_t *tinfo = CUR_THREAD_INFO; - if (sIsNuwaProcess && - (tinfo = CUR_THREAD_INFO) && - (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT)) { - return &tinfo->jmpEnv; - } - abort(); - return nullptr; -} - -MFBT_API bool -NuwaCheckpointCurrentThread2(int setjmpCond) { - thread_info_t *tinfo = CUR_THREAD_INFO; - if (setjmpCond == 0) { - REAL(pthread_mutex_lock)(&sThreadCountLock); - if (!(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) { - tinfo->flags |= TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT; - SaveTLSInfo(tinfo); - sThreadFreezeCount++; - } - pthread_cond_signal(&sThreadChangeCond); - pthread_mutex_unlock(&sThreadCountLock); - return true; - } - POST_SETJMP_RESTORE("NuwaCheckpointCurrentThread2"); - RECREATE_CONTINUE(); - RECREATE_GATE(); - return false; // Recreated thread. -} - -/** - * Register methods to be invoked before recreating threads in the spawned - * process. - */ -MFBT_API void -NuwaAddConstructor(void (*construct)(void *), void *arg) { - nuwa_construct_t ctr(construct, arg); - sConstructors.push_back(ctr); -} - -/** - * Register methods to be invoked after recreating threads in the spawned - * process. - */ -MFBT_API void -NuwaAddFinalConstructor(void (*construct)(void *), void *arg) { - nuwa_construct_t ctr(construct, arg); - sFinalConstructors.push_back(ctr); -} - -MFBT_API void -NuwaAddThreadConstructor(void (*aConstruct)(void *), void *aArg) { - thread_info *tinfo = CUR_THREAD_INFO; - if (!tinfo || !aConstruct) { - return; - } - - nuwa_construct_t construct(aConstruct, aArg); - tinfo->addThreadConstructor(&construct); -} - -/** - * @return if the current process is the nuwa process. - */ -MFBT_API bool -IsNuwaProcess() { - return sIsNuwaProcess; -} - -/** - * @return if the nuwa process is ready for spawning new processes. - */ -MFBT_API bool -IsNuwaReady() { - return sNuwaReady; -} - -#if defined(DEBUG) -MFBT_API void -NuwaAssertNotFrozen(unsigned int aThread, const char* aThreadName) { - if (!sIsNuwaProcess || !sIsFreezing) { - return; - } - - thread_info_t *tinfo = GetThreadInfo(static_cast(aThread)); - if (!tinfo) { - return; - } - - if ((tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) && - !(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) { - __android_log_print(ANDROID_LOG_FATAL, "Nuwa", - "Fatal error: the Nuwa process is about to deadlock in " - "accessing a frozen thread (%s, tid=%d).", - aThreadName ? aThreadName : "(unnamed)", - tinfo->origNativeThreadID); - abort(); - } -} -#endif - -} // extern "C" diff --git a/mozglue/build/Nuwa.h b/mozglue/build/Nuwa.h deleted file mode 100644 index 13d71ebfef023..0000000000000 --- a/mozglue/build/Nuwa.h +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set sw=2 ts=2 autoindent cindent expandtab: */ -/* 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 __NUWA_H_ -#define __NUWA_H_ - -#include -#include - -#include "mozilla/Types.h" - -/** - * Nuwa is a goddess who created mankind according to her figure in the - * ancient Chinese mythology. - */ - -// Max number of top level protocol that can be handled by Nuwa process. -#ifndef NUWA_TOPLEVEL_MAX -#define NUWA_TOPLEVEL_MAX 8 -#endif - -struct NuwaProtoFdInfo { - int protoId; - int originFd; - int newFds[2]; -}; - -#define NUWA_NEWFD_PARENT 0 -#define NUWA_NEWFD_CHILD 1 - -extern "C" { - -/** - * The following 3 methods are used to synchronously spawn the Nuwa process. - * The typical usage is: - * - * The IPC thread The main thread - * 1. Receives the request. - * 2. NuwaSpawnPrepare(). - * 3. Request main thread to - * spawn. --------------------------------------+ - * 4. NuwaSpawnWait(). V - * 5. NuwaSpawn() to clone all - * the threads in the Nuwa - * process (including main - * & IPC threads). - * 6. NuwaSpawn() finishes and - * +-------------------------------------- signals NuwaSpawnWait(). - * V - * 7. NuwaSpawnWait() returns. - */ - -/** - * Prepare for spawning a new process. The calling thread (typically the IPC - * thread) will block further requests to spawn a new process. - */ -MFBT_API void NuwaSpawnPrepare(); - -/** - * Called on the thread that receives the request. Used to wait until - * NuwaSpawn() finishes and maintain the stack of the calling thread. - */ -MFBT_API void NuwaSpawnWait(); - -/** - * Spawn a new content process, called in the Nuwa process. This has to run on - * the main thread. - * - * @return The process ID of the new process. - */ -MFBT_API pid_t NuwaSpawn(); - -/** - * The following methods are for marking threads created in the Nuwa process so - * they can be frozen and then recreated in the spawned process. All threads - * except the main thread must be marked by one of the following 4 methods; - * otherwise, we have a thread that is created but unknown to us. The Nuwa - * process will never become ready and this needs to be fixed. - */ - -/** - * Mark the current thread as supporting Nuwa. The thread will implicitly freeze - * by calling a blocking method such as pthread_mutex_lock() or epoll_wait(). - * - * @param recreate The custom function that will be called in the spawned - * process, after the thread is recreated. Can be nullptr if no - * custom function to be called after the thread is recreated. - * Note that this function is called duing thread recreation - * while other threads are frozen. It must not perform any - * action (e.g. acquiring a mutex) that might depend on another - * thread that is still blocked. - * @param arg The argument passed to the custom function. Can be nullptr. - */ -MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void *), void *arg); - -/** - * Mark the current thread as not supporting Nuwa. The calling thread will not - * be automatically cloned from the Nuwa process to spawned process. If this - * thread needs to be created in the spawned process, use NuwaAddConstructor() - * or NuwaAddFinalConstructor() to do it. - */ -MFBT_API void NuwaSkipCurrentThread(); - -/** - * Force the current thread to freeze explicitly at the current point. - */ -MFBT_API void NuwaFreezeCurrentThread(); - -/** - * Helper functions for the NuwaCheckpointCurrentThread() macro. - */ -MFBT_API jmp_buf* NuwaCheckpointCurrentThread1(); - -MFBT_API bool NuwaCheckpointCurrentThread2(int setjmpCond); - -/** - * Set the point to recover after thread recreation. The calling thread is not - * blocked. This is used for the thread that cannot freeze (i.e. the IPC - * thread). - */ -#define NuwaCheckpointCurrentThread() \ - NuwaCheckpointCurrentThread2(setjmp(*NuwaCheckpointCurrentThread1())) - -/** - * The following methods are called in the initialization stage of the Nuwa - * process. - */ - -/** - * Prepare for making the Nuwa process. - */ -MFBT_API void PrepareNuwaProcess(); - -/** - * Make the current process a Nuwa process. Start to freeze the threads. - */ -MFBT_API void MakeNuwaProcess(); - -/** - * Register a method to be invoked after a new process is spawned. The method - * will be invoked on the main thread *before* recreating the other threads. - * The registered method must not perform any action (e.g. acquiring a mutex) - * that might depend on another thread that has not yet been recreated. - * - * @param construct The method to be invoked. - * @param arg The argument passed to the method. - */ -MFBT_API void NuwaAddConstructor(void (*construct)(void *), void *arg); - - -/** - * Register a method to be invoked after a new process is spawned and threads - * are recreated. The method will be invoked on the main thread *after* - * the other threads are recreated and fully functional. - * - * @param construct The method to be invoked. - * @param arg The argument passed to the method. - */ -MFBT_API void NuwaAddFinalConstructor(void (*construct)(void *), void *arg); - - -/** - * Register a method to be invoked after the current thread is recreated in the - * spawned process. Note that this function is called while other threads are - * frozen. It must not perform any action (e.g. acquiring a mutex) that might - * depend on another thread that is still blocked. - * - * @param construct The method to be invoked. - * @param arg The argument passed to the method. - */ -MFBT_API void NuwaAddThreadConstructor(void (*construct)(void *), void *arg); - -/** - * The methods to query the Nuwa-related states. - */ - -/** - * @return If the current process is the Nuwa process. - */ -MFBT_API bool IsNuwaProcess(); - -/** - * @return If the Nuwa process is ready for spawning new processes. - */ -MFBT_API bool IsNuwaReady(); - -#if defined(DEBUG) -/** - * Asserts that aThread is not frozen. - */ -MFBT_API void NuwaAssertNotFrozen(unsigned int aThread, - const char* aThreadName); -#else -#define NuwaAssertNotFrozen(aThread, aThreadName) do {} while(0); -#endif -}; - -#endif /* __NUWA_H_ */ diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index 4065f17bd8363..b583501a18cc7 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -54,14 +54,6 @@ if not CONFIG['JS_STANDALONE']: 'version', ] - if CONFIG['MOZ_NUWA_PROCESS']: - EXPORTS.ipc += [ - 'Nuwa.h', - ] - SOURCES += [ - 'Nuwa.cpp', - ] - EXPORTS.mozilla += [ 'arm.h', 'mips.h', diff --git a/netwerk/base/Predictor.cpp b/netwerk/base/Predictor.cpp index 4e17f9260b61f..7939921060861 100644 --- a/netwerk/base/Predictor.cpp +++ b/netwerk/base/Predictor.cpp @@ -35,9 +35,6 @@ #include "nsStreamUtils.h" #include "nsString.h" #include "nsThreadUtils.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif #include "mozilla/Logging.h" #include "mozilla/Preferences.h" @@ -545,23 +542,6 @@ Predictor::GetInterface(const nsIID &iid, void **result) return QueryInterface(iid, result); } -#ifdef MOZ_NUWA_PROCESS -namespace { -class NuwaMarkPredictorThreadRunner : public Runnable -{ - NS_IMETHODIMP Run() override - { - MOZ_ASSERT(!NS_IsMainThread()); - - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } - return NS_OK; - } -}; -} // namespace -#endif - // Predictor::nsICacheEntryMetaDataVisitor #define SEEN_META_DATA "predictor::seen" @@ -770,11 +750,6 @@ Predictor::MaybeCleanupOldDBFiles() rv = NS_NewNamedThread("NetPredictClean", getter_AddRefs(ioThread)); RETURN_IF_FAILED(rv); -#ifdef MOZ_NUWA_PROCESS - nsCOMPtr nuwaRunner = new NuwaMarkPredictorThreadRunner(); - ioThread->Dispatch(nuwaRunner, NS_DISPATCH_NORMAL); -#endif - RefPtr runner = new PredictorOldCleanupRunner(ioThread, dbFile); ioThread->Dispatch(runner, NS_DISPATCH_NORMAL); diff --git a/netwerk/base/nsPACMan.cpp b/netwerk/base/nsPACMan.cpp index fd0b7dd7fdc63..a600e544d5312 100644 --- a/netwerk/base/nsPACMan.cpp +++ b/netwerk/base/nsPACMan.cpp @@ -17,9 +17,6 @@ #include "nsIAsyncVerifyRedirectCallback.h" #include "nsISystemProxySettings.h" #include "nsContentUtils.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif //----------------------------------------------------------------------------- @@ -764,11 +761,6 @@ nsPACMan::NamePACThread() { MOZ_ASSERT(!NS_IsMainThread(), "wrong thread"); PR_SetCurrentThreadName("Proxy Resolution"); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } -#endif } nsresult diff --git a/netwerk/base/nsSocketTransportService2.cpp b/netwerk/base/nsSocketTransportService2.cpp index 423081669d269..7dead9a066cd9 100644 --- a/netwerk/base/nsSocketTransportService2.cpp +++ b/netwerk/base/nsSocketTransportService2.cpp @@ -783,19 +783,9 @@ nsSocketTransportService::MarkTheLastElementOfPendingQueue() mServingPendingQueue = false; } -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - NS_IMETHODIMP nsSocketTransportService::Run() { -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } -#endif - SOCKET_LOG(("STS thread init %d sockets\n", gMaxCount)); psm::InitializeSSLServerCertVerificationThreads(); diff --git a/netwerk/base/nsStreamTransportService.cpp b/netwerk/base/nsStreamTransportService.cpp index 23ca3b860008f..3461480b6ca68 100644 --- a/netwerk/base/nsStreamTransportService.cpp +++ b/netwerk/base/nsStreamTransportService.cpp @@ -434,40 +434,6 @@ nsOutputStreamTransport::IsNonBlocking(bool *result) return NS_OK; } -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" - -class STSThreadPoolListener final : public nsIThreadPoolListener -{ -public: - NS_DECL_THREADSAFE_ISUPPORTS - NS_DECL_NSITHREADPOOLLISTENER - - STSThreadPoolListener() {} - -protected: - ~STSThreadPoolListener() {} -}; - -NS_IMPL_ISUPPORTS(STSThreadPoolListener, nsIThreadPoolListener) - -NS_IMETHODIMP -STSThreadPoolListener::OnThreadCreated() -{ - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } - return NS_OK; -} - -NS_IMETHODIMP -STSThreadPoolListener::OnThreadShuttingDown() -{ - return NS_OK; -} - -#endif // MOZ_NUWA_PROCESS - //----------------------------------------------------------------------------- // nsStreamTransportService //----------------------------------------------------------------------------- @@ -488,11 +454,6 @@ nsStreamTransportService::Init() mPool->SetThreadLimit(25); mPool->SetIdleThreadLimit(1); mPool->SetIdleThreadTimeout(PR_SecondsToInterval(30)); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - mPool->SetListener(new STSThreadPoolListener()); - } -#endif nsCOMPtr obsSvc = mozilla::services::GetObserverService(); diff --git a/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp index c4141dc5be3bd..3aaa8f930e3f8 100644 --- a/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp +++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp @@ -27,10 +27,6 @@ #include "mozilla/Base64.h" #include "mozilla/Telemetry.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - #ifdef MOZ_WIDGET_GONK #include #endif @@ -451,19 +447,6 @@ nsNotifyAddrListener::Observe(nsISupports *subject, return NS_OK; } -#ifdef MOZ_NUWA_PROCESS -class NuwaMarkLinkMonitorThreadRunner : public Runnable -{ - NS_IMETHODIMP Run() override - { - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } - return NS_OK; - } -}; -#endif - nsresult nsNotifyAddrListener::Init(void) { @@ -486,11 +469,6 @@ nsNotifyAddrListener::Init(void) rv = NS_NewNamedThread("Link Monitor", getter_AddRefs(mThread), this); NS_ENSURE_SUCCESS(rv, rv); -#ifdef MOZ_NUWA_PROCESS - nsCOMPtr runner = new NuwaMarkLinkMonitorThreadRunner(); - mThread->Dispatch(runner, NS_DISPATCH_NORMAL); -#endif - return NS_OK; } diff --git a/old-configure.in b/old-configure.in index 62c11568be505..07764ac38d0c2 100644 --- a/old-configure.in +++ b/old-configure.in @@ -4991,15 +4991,6 @@ if test -f "${srcdir}/${MOZ_BUILD_APP}/configure.in" ; then rm -f $tmpscript fi -dnl We need to wrap dlopen and related functions on Android because we use -dnl our own linker. -dnl This configuration will only work on Android SDK 11 and above: Bug 1220184. -if test "$OS_TARGET" = Android; then - if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then - MOZ_GLUE_WRAP_LDFLAGS="${MOZ_GLUE_WRAP_LDFLAGS} -Wl,--wrap=pthread_create,--wrap=epoll_wait,--wrap=poll,--wrap=pthread_cond_timedwait,--wrap=pthread_cond_wait,--wrap=epoll_create,--wrap=epoll_ctl,--wrap=close,--wrap=pthread_key_create,--wrap=pthread_key_delete,--wrap=socketpair,--wrap=pthread_self,--wrap=pthread_mutex_lock,--wrap=pthread_mutex_trylock,--wrap=pthread_join,--wrap=pipe,--wrap=pipe2" - fi -fi - AC_SUBST_LIST(MOZ_GLUE_WRAP_LDFLAGS) export MOZ_GLUE_WRAP_LDFLAGS @@ -6306,20 +6297,6 @@ AC_SUBST_LIST(MOZ_BZ2_LIBS) AC_SUBST_LIST(MOZ_PNG_CFLAGS) AC_SUBST_LIST(MOZ_PNG_LIBS) -if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_NUWA_PROCESS"; then - export MOZ_NUWA_PROCESS - AC_DEFINE(MOZ_NUWA_PROCESS) -fi -AC_SUBST(MOZ_NUWA_PROCESS) -if test "$MOZ_WIDGET_TOOLKIT" = gonk -a -n "$MOZ_B2G_LOADER"; then - if test -z "$MOZ_NUWA_PROCESS"; then - AC_MSG_ERROR([B2G loader works with Nuwa]); - fi - export MOZ_B2G_LOADER - AC_DEFINE(MOZ_B2G_LOADER) -fi -AC_SUBST(MOZ_B2G_LOADER) - AC_SUBST(MOZ_SYSTEM_NSPR) AC_SUBST(MOZ_SYSTEM_NSS) diff --git a/security/sandbox/linux/Sandbox.cpp b/security/sandbox/linux/Sandbox.cpp index 60f553fe7bc57..dde9af31715e3 100644 --- a/security/sandbox/linux/Sandbox.cpp +++ b/security/sandbox/linux/Sandbox.cpp @@ -506,19 +506,8 @@ SetCurrentProcessSandbox(UniquePtr aPolicy) } void -SandboxEarlyInit(GeckoProcessType aType, bool aIsNuwa) +SandboxEarlyInit(GeckoProcessType aType) { - // Bug 1168555: Nuwa isn't reliably single-threaded at this point; - // it starts an IPC I/O thread and then shuts it down before calling - // the plugin-container entry point, but that thread may not have - // finished exiting. If/when any type of sandboxing is used for the - // Nuwa process (e.g., unsharing the network namespace there instead - // of for each content process, to save memory), this will need to be - // changed by moving the SandboxEarlyInit call to an earlier point. - if (aIsNuwa) { - return; - } - const SandboxInfo info = SandboxInfo::Get(); if (info.Test(SandboxInfo::kUnexpectedThreads)) { return; diff --git a/security/sandbox/linux/Sandbox.h b/security/sandbox/linux/Sandbox.h index 513100a66427f..19defd76bf510 100644 --- a/security/sandbox/linux/Sandbox.h +++ b/security/sandbox/linux/Sandbox.h @@ -25,7 +25,7 @@ namespace mozilla { // This must be called early, while the process is still single-threaded. -MOZ_SANDBOX_EXPORT void SandboxEarlyInit(GeckoProcessType aType, bool aIsNuwa); +MOZ_SANDBOX_EXPORT void SandboxEarlyInit(GeckoProcessType aType); #ifdef MOZ_CONTENT_SANDBOX // Call only if SandboxInfo::CanSandboxContent() returns true. diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm index c282160f2c0b4..68b98e80608d9 100644 --- a/toolkit/components/extensions/Extension.jsm +++ b/toolkit/components/extensions/Extension.jsm @@ -1414,10 +1414,6 @@ Extension.prototype = extend(Object.create(ExtensionData.prototype), { broadcast(msg, data) { return new Promise(resolve => { let count = Services.ppmm.childCount; - if (AppConstants.MOZ_NUWA_PROCESS) { - // The nuwa process is frozen, so don't expect it to answer. - count--; - } Services.ppmm.addMessageListener(msg + "Complete", function listener() { count--; if (count == 0) { diff --git a/toolkit/modules/AppConstants.jsm b/toolkit/modules/AppConstants.jsm index 1ad24cbacab34..7c68414b02ea6 100644 --- a/toolkit/modules/AppConstants.jsm +++ b/toolkit/modules/AppConstants.jsm @@ -319,13 +319,6 @@ this.AppConstants = Object.freeze({ #endif SOURCE_REVISION_URL: "@MOZ_SOURCE_URL@", - MOZ_NUWA_PROCESS: -#ifdef MOZ_NUWA_PROCESS - true, -#else - false, -#endif - HAVE_USR_LIB64_DIR: #ifdef HAVE_USR_LIB64_DIR true, diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build index 7e42adeadaf9b..61085730e28e1 100644 --- a/toolkit/xre/moz.build +++ b/toolkit/xre/moz.build @@ -167,9 +167,6 @@ if CONFIG['MOZ_ENABLE_XREMOTE']: '/widget/xremoteclient', ] -if CONFIG['MOZ_B2G_LOADER']: - DEFINES['OMNIJAR_NAME'] = CONFIG['OMNIJAR_NAME'] - CXXFLAGS += CONFIG['TK_CFLAGS'] CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS'] CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 5601f5d80561d..17de71b2a339b 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -195,10 +195,6 @@ #include "base/command_line.h" #include "GTestRunner.h" -#ifdef MOZ_B2G_LOADER -#include "ProcessUtils.h" -#endif - #ifdef MOZ_WIDGET_ANDROID #include "GeneratedJNIWrappers.h" #endif @@ -3954,10 +3950,6 @@ XREMain::XRE_mainRun() nsresult rv = NS_OK; NS_ASSERTION(mScopedXPCOM, "Scoped xpcom not initialized."); -#ifdef MOZ_B2G_LOADER - mozilla::ipc::ProcLoaderClientGeckoInit(); -#endif - #ifdef NS_FUNCTION_TIMER // initialize some common services, so we don't pay the cost for these at odd times later on; // SetWindowCreator -> ChromeRegistry -> IOService -> SocketTransportService -> (nspr wspm init), Prefs diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index 72c99d722288f..2dcdee2070f59 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -90,11 +90,6 @@ using mozilla::_ipdltest::IPDLUnitTestProcessChild; #endif // ifdef MOZ_IPDL_TESTS -#ifdef MOZ_B2G_LOADER -#include "nsLocalFile.h" -#include "nsXREAppData.h" -#endif - #ifdef MOZ_JPROF #include "jprof.h" #endif @@ -949,40 +944,3 @@ XRE_InstallX11ErrorHandler() #endif } #endif - -#ifdef MOZ_B2G_LOADER -extern const nsXREAppData* gAppData; - -/** - * Preload static data of Gecko for B2G loader. - * - * This function is supposed to be called before XPCOM is initialized. - * For now, this function preloads - * - XPT interface Information - */ -void -XRE_ProcLoaderPreload(const char* aProgramDir, const nsXREAppData* aAppData) -{ - void PreloadXPT(nsIFile *); - - nsresult rv; - nsCOMPtr omnijarFile; - rv = NS_NewNativeLocalFile(nsCString(aProgramDir), - true, - getter_AddRefs(omnijarFile)); - MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); - - rv = omnijarFile->AppendNative(NS_LITERAL_CSTRING(NS_STRINGIFY(OMNIJAR_NAME))); - MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); - - /* - * gAppData is required by nsXULAppInfo. The manifest parser - * evaluate flags with the information from nsXULAppInfo. - */ - gAppData = aAppData; - - PreloadXPT(omnijarFile); - - gAppData = nullptr; -} -#endif /* MOZ_B2G_LOADER */ diff --git a/tools/profiler/core/ThreadInfo.h b/tools/profiler/core/ThreadInfo.h index 2f8d3f6474cf1..b5cb824292dbe 100644 --- a/tools/profiler/core/ThreadInfo.h +++ b/tools/profiler/core/ThreadInfo.h @@ -30,10 +30,6 @@ class ThreadInfo { virtual void SetPendingDelete(); bool IsPendingDelete() const { return mPendingDelete; } -#ifdef MOZ_NUWA_PROCESS - void SetThreadId(int aThreadId) { mThreadId = aThreadId; } -#endif - #ifndef SPS_STANDALONE /** * May be null for the main thread if the profiler was started during startup diff --git a/tools/profiler/core/platform-linux.cc b/tools/profiler/core/platform-linux.cc index 1b5f0a551ed73..0c3a13a05d18e 100644 --- a/tools/profiler/core/platform-linux.cc +++ b/tools/profiler/core/platform-linux.cc @@ -92,10 +92,6 @@ #include #include -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - #define SIGNAL_SAVE_PROFILE SIGUSR2 using namespace mozilla; @@ -300,18 +296,6 @@ static void* SignalSender(void* arg) { // Taken from platform_thread_posix.cc prctl(PR_SET_NAME, "SamplerThread", 0, 0, 0); -#ifdef MOZ_NUWA_PROCESS - // If the Nuwa process is enabled, we need to mark and freeze the sampler - // thread in the Nuwa process and have this thread recreated in the spawned - // child. - if(IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - // Freeze the thread here so the spawned child will get the correct tgid - // from the getpid() call below. - NuwaFreezeCurrentThread(); - } -#endif - int vm_tgid_ = getpid(); DebugOnly my_tid = gettid(); @@ -500,18 +484,6 @@ void Sampler::Stop() { } } -#ifdef MOZ_NUWA_PROCESS -static void -UpdateThreadId(void* aThreadInfo) { - ThreadInfo* info = static_cast(aThreadInfo); - // Note that this function is called during thread recreation. Only the thread - // calling this method is running. We can't try to acquire - // Sampler::sRegisteredThreadsMutex because it could be held by another - // thread. - info->SetThreadId(gettid()); -} -#endif - bool Sampler::RegisterCurrentThread(const char* aName, PseudoStack* aPseudoStack, bool aIsMainThread, void* stackTop) @@ -543,20 +515,6 @@ bool Sampler::RegisterCurrentThread(const char* aName, sRegisteredThreads->push_back(info); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - if (info->IsMainThread()) { - // Main thread isn't a marked thread. Register UpdateThreadId() to - // NuwaAddConstructor(), which runs before all other threads are - // recreated. - NuwaAddConstructor(UpdateThreadId, info); - } else { - // Register UpdateThreadInfo() to be run when the thread is recreated. - NuwaAddThreadConstructor(UpdateThreadId, info); - } - } -#endif - return true; } diff --git a/widget/gonk/GonkMemoryPressureMonitoring.cpp b/widget/gonk/GonkMemoryPressureMonitoring.cpp index e0e54f3cd09c9..d014ce54c861e 100644 --- a/widget/gonk/GonkMemoryPressureMonitoring.cpp +++ b/widget/gonk/GonkMemoryPressureMonitoring.cpp @@ -26,10 +26,6 @@ #define LOG(args...) \ __android_log_print(ANDROID_LOG_INFO, "GonkMemoryPressure" , ## args) -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - using namespace mozilla; namespace { @@ -123,12 +119,6 @@ class MemoryPressureWatcher final { MOZ_ASSERT(!NS_IsMainThread()); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } -#endif - int triggerResetTimeout = -1; bool memoryPressure; nsresult rv = CheckForMemoryPressure(&memoryPressure); diff --git a/widget/gonk/nsAppShell.cpp b/widget/gonk/nsAppShell.cpp index f6ed33a061cb5..b0e8dee2943b8 100644 --- a/widget/gonk/nsAppShell.cpp +++ b/widget/gonk/nsAppShell.cpp @@ -63,10 +63,6 @@ #include "libui/InputReader.h" #include "libui/InputDispatcher.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - #include "mozilla/Preferences.h" #include "GeckoProfiler.h" @@ -909,11 +905,6 @@ nsAppShell::Init() obsServ->AddObserver(this, "network-connection-state-changed", false); } -#ifdef MOZ_NUWA_PROCESS - // Make sure main thread was woken up after Nuwa fork. - NuwaAddConstructor((void (*)(void *))&NotifyEvent, nullptr); -#endif - // Delay initializing input devices until the screen has been // initialized (and we know the resolution). return rv; diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index fa10ed6c1a8b2..8b1a45748dd1c 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -1246,10 +1246,6 @@ enum ccType ShutdownCC /* Shutdown CC, used for finding leaks. */ }; -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - //////////////////////////////////////////////////////////////////////// // Top level structure for the cycle collector. //////////////////////////////////////////////////////////////////////// diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index 9a046075523bf..380cf2b3505fd 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -1926,12 +1926,6 @@ nsMemoryReporterManager::HandleChildReport( nsMemoryReporterManager::StartChildReport(mozilla::dom::ContentParent* aChild, const PendingProcessesState* aState) { -#ifdef MOZ_NUWA_PROCESS - if (aChild->IsNuwaProcess()) { - return false; - } -#endif - if (!aChild->IsAlive()) { MEMORY_REPORTING_LOG("StartChildReports (gen=%u): child exited before" " its report was started\n", @@ -1984,7 +1978,7 @@ nsMemoryReporterManager::EndProcessReport(uint32_t aGeneration, bool aSuccess) RefPtr nextChild; nextChild.swap(s->mChildrenPending.LastElement()); s->mChildrenPending.TruncateLength(s->mChildrenPending.Length() - 1); - // Start report (if the child is still alive and not Nuwa). + // Start report (if the child is still alive). if (StartChildReport(nextChild, s)) { ++s->mNumProcessesRunning; MEMORY_REPORTING_LOG("HandleChildReports (aGen=%u): started child report" diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h index c7fdf8d79f6a6..a87e85ab1445c 100644 --- a/xpcom/build/nsXULAppAPI.h +++ b/xpcom/build/nsXULAppAPI.h @@ -508,18 +508,6 @@ XRE_API(void, XRE_API(void, XRE_StopLateWriteChecks, (void)) -#ifdef MOZ_B2G_LOADER -XRE_API(int, - XRE_ProcLoaderServiceRun, (pid_t, int, int argc, const char* argv[], - mozilla::Vector& aReservedFds)); -XRE_API(void, - XRE_ProcLoaderClientInit, (pid_t, int, - mozilla::Vector& aReservedFds)); -XRE_API(void, - XRE_ProcLoaderPreload, (const char* aProgramDir, - const nsXREAppData* aAppData)); -#endif // MOZ_B2G_LOADER - XRE_API(void, XRE_EnableSameExecutableForContentProc, ()) diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp index 613a188970152..4dcfc8402c837 100644 --- a/xpcom/components/ManifestParser.cpp +++ b/xpcom/components/ManifestParser.cpp @@ -37,18 +37,6 @@ #include "nsIScriptError.h" #include "nsIXULAppInfo.h" #include "nsIXULRuntime.h" -#ifdef MOZ_B2G_LOADER -#include "mozilla/XPTInterfaceInfoManager.h" -#endif - -#ifdef MOZ_B2G_LOADER -#define XPTONLY_MANIFEST &nsComponentManagerImpl::XPTOnlyManifestManifest -#define XPTONLY_XPT &nsComponentManagerImpl::XPTOnlyManifestXPT -#else -#define XPTONLY_MANIFEST nullptr -#define XPTONLY_XPT nullptr -#endif - using namespace mozilla; @@ -78,21 +66,14 @@ struct ManifestDirective void (nsChromeRegistry::*regfunc)( nsChromeRegistry::ManifestProcessingContext& aCx, int aLineNo, char* const* aArgv, int aFlags); -#ifdef MOZ_B2G_LOADER - // The function to handle the directive for XPT Only parsing. - void (*xptonlyfunc)( - nsComponentManagerImpl::XPTOnlyManifestProcessingContext& aCx, - int aLineNo, char* const* aArgv); -#else void* xptonlyfunc; -#endif bool isContract; }; static const ManifestDirective kParsingTable[] = { { "manifest", 1, false, false, true, true, false, - &nsComponentManagerImpl::ManifestManifest, nullptr, XPTONLY_MANIFEST + &nsComponentManagerImpl::ManifestManifest, nullptr, nullptr }, { "binary-component", 1, true, true, false, false, false, @@ -100,7 +81,7 @@ static const ManifestDirective kParsingTable[] = { }, { "interfaces", 1, false, true, false, false, false, - &nsComponentManagerImpl::ManifestXPT, nullptr, XPTONLY_XPT + &nsComponentManagerImpl::ManifestXPT, nullptr, nullptr }, { "component", 2, false, true, false, false, false, @@ -484,9 +465,6 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, nsComponentManagerImpl::ManifestProcessingContext mgrcx(aType, aFile, aChromeOnly); nsChromeRegistry::ManifestProcessingContext chromecx(aType, aFile); -#ifdef MOZ_B2G_LOADER - nsComponentManagerImpl::XPTOnlyManifestProcessingContext xptonlycx(aFile); -#endif nsresult rv; NS_NAMED_LITERAL_STRING(kPlatform, "platform"); @@ -775,11 +753,6 @@ ParseManifest(NSLocationType aType, FileLocation& aFile, char* aBuf, continue; } -#ifdef MOZ_B2G_LOADER - if (aXPTOnly) { - directive->xptonlyfunc(xptonlycx, line, argv); - } else -#endif /* MOZ_B2G_LOADER */ if (directive->regfunc) { if (GeckoProcessType_Default != XRE_GetProcessType()) { continue; diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp index b8f280b04f530..6ccc27758e31d 100644 --- a/xpcom/components/nsComponentManager.cpp +++ b/xpcom/components/nsComponentManager.cpp @@ -107,36 +107,6 @@ NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID); #define UID_STRING_LENGTH 39 -#ifdef MOZ_B2G_LOADER -typedef nsDataHashtable XPTIInfosBookType; -static XPTIInfosBookType* sXPTIInfosBook = nullptr; - -static XPTIInfosBookType* -GetXPTIInfosBook() -{ - if (!sXPTIInfosBook) { - sXPTIInfosBook = new XPTIInfosBookType; - } - return sXPTIInfosBook; -} - -static bool -IsRegisteredXPTIInfo(FileLocation& aFile) -{ - nsAutoCString uri; - aFile.GetURIString(uri); - return GetXPTIInfosBook()->Get(uri); -} - -static void -MarkRegisteredXPTIInfo(FileLocation& aFile) -{ - nsAutoCString uri; - aFile.GetURIString(uri); - GetXPTIInfosBook()->Put(uri, true); -} -#endif /* MOZ_B2G_LOADER */ - nsresult nsGetServiceFromCategory::operator()(const nsIID& aIID, void** aInstancePtr) const @@ -682,12 +652,6 @@ nsComponentManagerImpl::ManifestBinaryComponent(ManifestProcessingContext& aCx, static void DoRegisterXPT(FileLocation& aFile) { -#ifdef MOZ_B2G_LOADER - if (IsRegisteredXPTIInfo(aFile)) { - return; - } -#endif - uint32_t len; FileLocation::Data data; UniquePtr buf; @@ -701,9 +665,6 @@ DoRegisterXPT(FileLocation& aFile) } if (NS_SUCCEEDED(rv)) { XPTInterfaceInfoManager::GetSingleton()->RegisterBuffer(buf.get(), len); -#ifdef MOZ_B2G_LOADER - MarkRegisteredXPTIInfo(aFile); -#endif } else { nsCString uri; aFile.GetURIString(uri); @@ -911,10 +872,6 @@ nsresult nsComponentManagerImpl::Shutdown(void) delete sStaticModules; delete sModuleLocations; -#ifdef MOZ_B2G_LOADER - delete sXPTIInfosBook; - sXPTIInfosBook = nullptr; -#endif // Unload libraries mNativeModuleLoader.UnloadLibraries(); @@ -2072,52 +2029,6 @@ nsComponentManagerImpl::GetManifestLocations(nsIArray** aLocations) return NS_OK; } -#ifdef MOZ_B2G_LOADER - -/* static */ -void -nsComponentManagerImpl::XPTOnlyManifestManifest( - XPTOnlyManifestProcessingContext& aCx, int aLineNo, char* const* aArgv) -{ - char* file = aArgv[0]; - FileLocation f(aCx.mFile, file); - - DoRegisterManifest(NS_APP_LOCATION, f, false, true); -} - -/* static */ -void -nsComponentManagerImpl::XPTOnlyManifestXPT( - XPTOnlyManifestProcessingContext& aCx, int aLineNo, char* const* aArgv) -{ - FileLocation f(aCx.mFile, aArgv[0]); - DoRegisterXPT(f); -} - -/** - * To load XPT Interface Information before the component manager is ready. - * - * With this function, B2G loader could XPT interface info. as earier - * as possible to gain benefit of shared memory model of the kernel. - */ -/* static */ void -nsComponentManagerImpl::PreloadXPT(nsIFile* aFile) -{ - MOZ_ASSERT(!nsComponentManagerImpl::gComponentManager); - FileLocation location(aFile, "chrome.manifest"); - - DoRegisterManifest(NS_APP_LOCATION, location, - false, true /* aXPTOnly */); -} - -void -PreloadXPT(nsIFile* aOmnijarFile) -{ - nsComponentManagerImpl::PreloadXPT(aOmnijarFile); -} - -#endif /* MOZ_B2G_LOADER */ - EXPORT_XPCOM_API(nsresult) XRE_AddManifestLocation(NSLocationType aType, nsIFile* aLocation) { diff --git a/xpcom/components/nsComponentManager.h b/xpcom/components/nsComponentManager.h index f2f86ca896217..f0e0f684a109c 100644 --- a/xpcom/components/nsComponentManager.h +++ b/xpcom/components/nsComponentManager.h @@ -40,10 +40,6 @@ #include "mozilla/Omnijar.h" #include "mozilla/Attributes.h" -#ifdef MOZ_B2G_LOADER -#include "mozilla/FileLocation.h" -#endif - struct nsFactoryEntry; class nsIServiceManager; struct PRThread; @@ -334,31 +330,6 @@ class nsComponentManagerImpl final size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; -#ifdef MOZ_B2G_LOADER - // Preload XPT interface info for B2G loader. - // This function is called before XPCOM has been initialized. - static void PreloadXPT(nsIFile* aFile); -#endif - -#ifdef MOZ_B2G_LOADER - // Parsing functions of directives of manifest for XPT only parsing. - struct XPTOnlyManifestProcessingContext - { - XPTOnlyManifestProcessingContext(mozilla::FileLocation& aFile) - : mFile(aFile) - { - } - - ~XPTOnlyManifestProcessingContext() {} - - mozilla::FileLocation mFile; - }; - static void XPTOnlyManifestManifest(XPTOnlyManifestProcessingContext& aCx, - int aLineNo, char* const* aArgv); - static void XPTOnlyManifestXPT(XPTOnlyManifestProcessingContext& aCx, - int aLineNo, char* const* aArgv); -#endif - private: ~nsComponentManagerImpl(); }; diff --git a/xpcom/threads/BackgroundHangMonitor.cpp b/xpcom/threads/BackgroundHangMonitor.cpp index ba674cbfbe7f3..46ee84f6ec9d8 100644 --- a/xpcom/threads/BackgroundHangMonitor.cpp +++ b/xpcom/threads/BackgroundHangMonitor.cpp @@ -14,9 +14,6 @@ #include "mozilla/Telemetry.h" #include "mozilla/ThreadHangStats.h" #include "mozilla/ThreadLocal.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif #include "prinrval.h" #include "prthread.h" @@ -59,12 +56,6 @@ class BackgroundHangManager : public nsIObserver { PR_SetCurrentThreadName("BgHangManager"); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } -#endif - /* We do not hold a reference to BackgroundHangManager here because the monitor thread only exists as long as the BackgroundHangManager instance exists. We stop the monitor diff --git a/xpcom/threads/HangMonitor.cpp b/xpcom/threads/HangMonitor.cpp index 911bccbd7d944..e051c58ae0f57 100644 --- a/xpcom/threads/HangMonitor.cpp +++ b/xpcom/threads/HangMonitor.cpp @@ -23,10 +23,6 @@ #include "nsExceptionHandler.h" #endif -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - #ifdef XP_WIN #include #endif @@ -184,12 +180,6 @@ ThreadMain(void*) { PR_SetCurrentThreadName("Hang Monitor"); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } -#endif - MonitorAutoLock lock(*gMonitor); // In order to avoid issues with the hang monitor incorrectly triggering diff --git a/xpcom/threads/TimerThread.cpp b/xpcom/threads/TimerThread.cpp index e2129c95929fe..ad905c794db9c 100644 --- a/xpcom/threads/TimerThread.cpp +++ b/xpcom/threads/TimerThread.cpp @@ -386,10 +386,6 @@ TimerThread::Shutdown() return NS_OK; } -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif - namespace { struct MicrosecondsToInterval @@ -413,12 +409,6 @@ TimerThread::Run() { PR_SetCurrentThreadName("Timer"); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } -#endif - MonitorAutoLock lock(mMonitor); // We need to know how many microseconds give a positive PRIntervalTime. This @@ -446,11 +436,7 @@ TimerThread::Run() bool forceRunThisTimer = forceRunNextTimer; forceRunNextTimer = false; - if (mSleeping -#ifdef MOZ_NUWA_PROCESS - || IsNuwaProcess() // Don't fire timers or deadlock will result. -#endif - ) { + if (mSleeping) { // Sleep for 0.1 seconds while not firing timers. uint32_t milliseconds = 100; if (ChaosMode::isActive(ChaosFeature::TimerScheduling)) { diff --git a/xpcom/threads/nsThread.cpp b/xpcom/threads/nsThread.cpp index f54ea0326434b..2a4b7854d0686 100644 --- a/xpcom/threads/nsThread.cpp +++ b/xpcom/threads/nsThread.cpp @@ -43,10 +43,6 @@ #include "mozilla/dom/ContentChild.h" #endif -#ifdef MOZ_NUWA_PROCESS -#include "private/pprthred.h" -#endif - #ifdef XP_LINUX #include #include @@ -677,12 +673,6 @@ nsThread::PutEvent(already_AddRefed aEvent, nsNestedEventTarget* aT LeakRefPtr event(Move(aEvent)); nsCOMPtr obs; -#ifdef MOZ_NUWA_PROCESS - // On debug build or when tests are enabled, assert that we are not about to - // create a deadlock in the Nuwa process. - NuwaAssertNotFrozen(PR_GetThreadID(mThread), PR_GetThreadName(mThread)); -#endif - { MutexAutoLock lock(mLock); nsChainedEventQueue* queue = aTarget ? aTarget->mQueue : &mEventsRoot; diff --git a/xpcom/threads/nsTimerImpl.cpp b/xpcom/threads/nsTimerImpl.cpp index f2aa3e4e89d6f..a9594ae70e38a 100644 --- a/xpcom/threads/nsTimerImpl.cpp +++ b/xpcom/threads/nsTimerImpl.cpp @@ -14,9 +14,6 @@ #include "mozilla/Atomics.h" #include "mozilla/IntegerPrintfMacros.h" #include "mozilla/Logging.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif #ifdef MOZ_TASK_TRACER #include "GeckoTaskTracerImpl.h" using namespace mozilla::tasktracer;