void PluginProcessParent::Delete() { MessageLoop* currentLoop = MessageLoop::current(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); if (currentLoop == ioLoop) { delete this; return; } ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &PluginProcessParent::Delete)); }
mozilla::ipc::IPCResult GPUParent::RecvNewWidgetCompositor(Endpoint<layers::PCompositorBridgeParent>&& aEndpoint, const CSSToLayoutDeviceScale& aScale, const TimeDuration& aVsyncRate, const bool& aUseExternalSurfaceSize, const IntSize& aSurfaceSize) { RefPtr<CompositorBridgeParent> cbp = new CompositorBridgeParent(aScale, aVsyncRate, aUseExternalSurfaceSize, aSurfaceSize); MessageLoop* loop = CompositorThreadHolder::Loop(); loop->PostTask(NewRunnableFunction(OpenParent, cbp, Move(aEndpoint))); return IPC_OK(); }
bool GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs, base::ProcessArchitecture arch) { PrepareLaunch(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI"); ioLoop->PostTask(NewNonOwningRunnableMethod <std::vector<std::string>, base::ProcessArchitecture> (this, &GeckoChildProcessHost::RunPerformAsyncLaunch, aExtraOpts, arch)); return WaitUntilConnected(aTimeoutMs); }
void TexturePoolOGL::MaybeFillTextures() { if (sTextures->GetSize() < TEXTURE_REFILL_THRESHOLD && !sHasPendingFillTask) { LOG("need to refill the texture pool."); sHasPendingFillTask = true; MessageLoop* loop = mozilla::layers::CompositorThreadHolder::Loop(); MOZ_ASSERT(loop); loop->PostTask( NS_NewRunnableFunction( "TexturePoolOGL::MaybeFillTextures", [] () { TexturePoolOGL::Fill(sActiveContext); })); } }
/*static*/ PImageBridgeParent* ImageBridgeParent::Create(Transport* aTransport, ProcessId aChildProcessId) { base::ProcessHandle processHandle; if (!base::OpenProcessHandle(aChildProcessId, &processHandle)) { return nullptr; } MessageLoop* loop = CompositorParent::CompositorLoop(); nsRefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport, aChildProcessId); bridge->mSelfRef = bridge; loop->PostTask(FROM_HERE, NewRunnableFunction(ConnectImageBridgeInParentProcess, bridge.get(), aTransport, processHandle)); return bridge.get(); }
/*static*/ bool ImageBridgeParent::Create(Transport* aTransport, ProcessId aOtherProcess) { ProcessHandle processHandle; if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) { return false; } MessageLoop* loop = CompositorParent::CompositorLoop(); nsRefPtr<ImageBridgeParent> bridge = new ImageBridgeParent(loop, aTransport); bridge->mSelfRef = bridge; loop->PostTask(FROM_HERE, NewRunnableFunction(ConnectImageBridgeInParentProcess, bridge.get(), aTransport, processHandle)); return true; }
NS_IMETHODIMP DoWorkRunnable::Run() { MessageLoop* loop = MessageLoop::current(); MOZ_ASSERT(loop); bool nestableTasksAllowed = loop->NestableTasksAllowed(); // MessageLoop::RunTask() disallows nesting, but our Frankenventloop will // always dispatch DoWork() below from what looks to MessageLoop like a nested // context. So we unconditionally allow nesting here. loop->SetNestableTasksAllowed(true); loop->DoWork(); loop->SetNestableTasksAllowed(nestableTasksAllowed); return NS_OK; }
void SfDelegate::initiateConnection( const char *uri, const KeyedVector<String8, String8> *headers, off64_t offset) { GURL url(uri); MessageLoop *loop = gNetworkThread->message_loop(); loop->PostTask( FROM_HERE, NewRunnableFunction( &SfDelegate::OnInitiateConnectionWrapper, this, url, headers, offset)); }
NS_IMETHODIMP DoWorkRunnable::Run() { MessageLoop* loop = MessageLoop::current(); NS_ASSERTION(loop, "Shouldn't be null!"); if (loop) { bool nestableTasksAllowed = loop->NestableTasksAllowed(); // MessageLoop::RunTask() disallows nesting, but our Frankenventloop // will always dispatch DoWork() below from what looks to // MessageLoop like a nested context. So we unconditionally allow // nesting here. loop->SetNestableTasksAllowed(true); loop->DoWork(); loop->SetNestableTasksAllowed(nestableTasksAllowed); } return NS_OK; }
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType, base::WaitableEventWatcher::Delegate* aDelegate) : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum mProcessType(aProcessType), mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"), mLaunched(false), mChannelInitialized(false), mDelegate(aDelegate), mChildProcessHandle(0) { MOZ_COUNT_CTOR(GeckoChildProcessHost); MessageLoop* ioLoop = BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::InitializeChannel)); }
void MessagePumpForChildProcess::Run(MessagePump::Delegate* aDelegate) { if (mFirstRun) { #ifdef DEBUG NS_ASSERTION(aDelegate && gFirstDelegate == nullptr, "Huh?!"); gFirstDelegate = aDelegate; #endif mFirstRun = false; if (NS_FAILED(XRE_RunAppShell())) { NS_WARNING("Failed to run app shell?!"); } #ifdef DEBUG NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!"); gFirstDelegate = nullptr; #endif return; } #ifdef DEBUG NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!"); #endif // We can get to this point in startup with Tasks in our loop's // incoming_queue_ or pending_queue_, but without a matching // DoWorkRunnable(). In MessagePump::Run() above, we sensitively // depend on *not* directly calling delegate->DoWork(), because that // prioritizes Tasks above XPCOM events. However, from this point // forward, any Task posted to our loop is guaranteed to have a // DoWorkRunnable enqueued for it. // // So we just flush the pending work here and move on. MessageLoop* loop = MessageLoop::current(); bool nestableTasksAllowed = loop->NestableTasksAllowed(); loop->SetNestableTasksAllowed(true); while (aDelegate->DoWork()); loop->SetNestableTasksAllowed(nestableTasksAllowed); // Really run. mozilla::ipc::MessagePump::Run(aDelegate); }
bool GeckoChildProcessHost::LaunchAndWaitForProcessHandle(StringVector aExtraOpts) { PrepareLaunch(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::RunPerformAsyncLaunch, aExtraOpts, base::GetCurrentProcessArchitecture())); MonitorAutoLock lock(mMonitor); while (mProcessState < PROCESS_CREATED) { lock.Wait(); } MOZ_ASSERT(mProcessState == PROCESS_ERROR || mChildProcessHandle); return mProcessState < PROCESS_ERROR; }
bool GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTimeoutMs, base::ProcessArchitecture arch) { PrepareLaunch(); PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ? PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT; MessageLoop* ioLoop = XRE_GetIOMessageLoop(); NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI"); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::RunPerformAsyncLaunch, aExtraOpts, arch)); // NB: this uses a different mechanism than the chromium parent // class. MonitorAutoLock lock(mMonitor); PRIntervalTime waitStart = PR_IntervalNow(); PRIntervalTime current; // We'll receive several notifications, we need to exit when we // have either successfully launched or have timed out. while (mProcessState != PROCESS_CONNECTED) { // If there was an error then return it, don't wait out the timeout. if (mProcessState == PROCESS_ERROR) { break; } lock.Wait(timeoutTicks); if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) { current = PR_IntervalNow(); PRIntervalTime elapsed = current - waitStart; if (elapsed > timeoutTicks) { break; } timeoutTicks = timeoutTicks - elapsed; waitStart = current; } } return mProcessState == PROCESS_CONNECTED; }
bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) { MessageLoop* ioLoop = BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::PerformAsyncLaunch, aExtraOpts)); // This may look like the sync launch wait, but we only delay as // long as it takes to create the channel. MonitorAutoEnter mon(mMonitor); while (!mChannelInitialized) { mon.Wait(); } return true; }
nsresult BluetoothDaemonConnection::ConnectSocket(BluetoothDaemonPDUConsumer* aConsumer) { MOZ_ASSERT(NS_IsMainThread()); if (mIO) { CHROMIUM_LOG("Bluetooth daemon already connecting/connected!"); return NS_ERROR_FAILURE; } SetConnectionStatus(SOCKET_CONNECTING); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); mIO = new BluetoothDaemonConnectionIO( ioLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING, this, aConsumer); ioLoop->PostTask(FROM_HERE, new BluetoothDaemonConnectTask(mIO)); return NS_OK; }
bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) { PrepareLaunch(); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::RunPerformAsyncLaunch, aExtraOpts, base::GetCurrentProcessArchitecture())); // This may look like the sync launch wait, but we only delay as // long as it takes to create the channel. MonitorAutoLock lock(mMonitor); while (mProcessState < CHANNEL_INITIALIZED) { lock.Wait(); } return true; }
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType, base::WaitableEventWatcher::Delegate* aDelegate) : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum mProcessType(aProcessType), mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"), mLaunched(false), mChannelInitialized(false), mDelegate(aDelegate), mChildProcessHandle(0) #if defined(MOZ_WIDGET_COCOA) , mChildTask(MACH_PORT_NULL) #endif { MOZ_COUNT_CTOR(GeckoChildProcessHost); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::InitializeChannel)); }
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType, ChildPrivileges aPrivileges) : ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum mProcessType(aProcessType), mPrivileges(aPrivileges), mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"), mProcessState(CREATING_CHANNEL), mDelegate(nullptr), mChildProcessHandle(0) #if defined(MOZ_WIDGET_COCOA) , mChildTask(MACH_PORT_NULL) #endif { MOZ_COUNT_CTOR(GeckoChildProcessHost); MessageLoop* ioLoop = XRE_GetIOMessageLoop(); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::InitializeChannel)); }
bool GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts) { MessageLoop* ioLoop = BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO); NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI"); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::PerformAsyncLaunch, aExtraOpts)); // NB: this uses a different mechanism than the chromium parent // class. MonitorAutoEnter mon(mMonitor); while (!mLaunched) { mon.Wait(); } return true; }
bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) { #ifdef XP_WIN InitWindowsGroupID(); #endif MessageLoop* ioLoop = XRE_GetIOMessageLoop(); ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GeckoChildProcessHost::PerformAsyncLaunch, aExtraOpts, base::GetCurrentProcessArchitecture())); // This may look like the sync launch wait, but we only delay as // long as it takes to create the channel. MonitorAutoLock lock(mMonitor); while (!mChannelInitialized) { lock.Wait(); } return true; }
nsresult XRE_RunAppShell() { nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID)); NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE); #if defined(XP_MACOSX) { // In content processes that want XPCOM (and hence want // AppShell), we usually run our hybrid event loop through // MessagePump::Run(), by way of nsBaseAppShell::Run(). The // Cocoa nsAppShell impl, however, implements its own Run() // that's unaware of MessagePump. That's all rather suboptimal, // but oddly enough not a problem... usually. // // The problem with this setup comes during startup. // XPCOM-in-subprocesses depends on IPC, e.g. to init the pref // service, so we have to init IPC first. But, IPC also // indirectly kinda-depends on XPCOM, because MessagePump // schedules work from off-main threads (e.g. IO thread) by // using NS_DispatchToMainThread(). If the IO thread receives a // Message from the parent before nsThreadManager is // initialized, then DispatchToMainThread() will fail, although // MessagePump will remember the task. This race condition // isn't a problem when appShell->Run() ends up in // MessagePump::Run(), because MessagePump will immediate see it // has work to do. It *is* a problem when we end up in [NSApp // run], because it's not aware that MessagePump has work that // needs to be processed; that was supposed to be signaled by // nsIRunnable(s). // // So instead of hacking Cocoa nsAppShell or rewriting the // event-loop system, we compromise here by processing any tasks // that might have been enqueued on MessagePump, *before* // MessagePump::ScheduleWork was able to successfully // DispatchToMainThread(). MessageLoop* loop = MessageLoop::current(); bool couldNest = loop->NestableTasksAllowed(); loop->SetNestableTasksAllowed(true); RefPtr<Runnable> task = new MessageLoop::QuitTask(); loop->PostTask(task.forget()); loop->Run(); loop->SetNestableTasksAllowed(couldNest); } #endif // XP_MACOSX return appShell->Run(); }
NS_InitXPCOM2(nsIServiceManager** aResult, nsIFile* aBinDirectory, nsIDirectoryServiceProvider* aAppFileLocationProvider) { static bool sInitialized = false; if (sInitialized) { return NS_ERROR_FAILURE; } sInitialized = true; mozPoisonValueInit(); NS_LogInit(); mozilla::LogModule::Init(); JS_SetCurrentEmbedderTimeFunction(TimeSinceProcessCreation); char aLocal; profiler_init(&aLocal); nsresult rv = NS_OK; // We are not shutting down gXPCOMShuttingDown = false; // Initialize the available memory tracker before other threads have had a // chance to start up, because the initialization is not thread-safe. mozilla::AvailableMemoryTracker::Init(); #ifdef XP_UNIX // Discover the current value of the umask, and save it where // nsSystemInfo::Init can retrieve it when necessary. There is no way // to read the umask without changing it, and the setting is process- // global, so this must be done while we are still single-threaded; the // nsSystemInfo object is typically created much later, when some piece // of chrome JS wants it. The system call is specified as unable to fail. nsSystemInfo::gUserUmask = ::umask(0777); ::umask(nsSystemInfo::gUserUmask); #endif // Set up chromium libs NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!"); if (!AtExitManager::AlreadyRegistered()) { sExitManager = new AtExitManager(); } MessageLoop* messageLoop = MessageLoop::current(); if (!messageLoop) { sMessageLoop = new MessageLoopForUI(MessageLoop::TYPE_MOZILLA_PARENT); sMessageLoop->set_thread_name("Gecko"); // Set experimental values for main thread hangs: // 128ms for transient hangs and 8192ms for permanent hangs sMessageLoop->set_hang_timeouts(128, 8192); } else if (messageLoop->type() == MessageLoop::TYPE_MOZILLA_CHILD) { messageLoop->set_thread_name("Gecko_Child"); messageLoop->set_hang_timeouts(128, 8192); } if (XRE_IsParentProcess() && !BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO)) { UniquePtr<BrowserProcessSubThread> ioThread = MakeUnique<BrowserProcessSubThread>(BrowserProcessSubThread::IO); base::Thread::Options options; options.message_loop_type = MessageLoop::TYPE_IO; if (NS_WARN_IF(!ioThread->StartWithOptions(options))) { return NS_ERROR_FAILURE; } sIOThread = ioThread.release(); } // Establish the main thread here. rv = nsThreadManager::get()->Init(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // Set up the timer globals/timer thread rv = nsTimerImpl::Startup(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } #ifndef ANDROID // If the locale hasn't already been setup by our embedder, // get us out of the "C" locale and into the system if (strcmp(setlocale(LC_ALL, nullptr), "C") == 0) { setlocale(LC_ALL, ""); } #endif #if defined(XP_UNIX) NS_StartupNativeCharsetUtils(); #endif NS_StartupLocalFile(); StartupSpecialSystemDirectory(); nsDirectoryService::RealInit(); bool value; if (aBinDirectory) { rv = aBinDirectory->IsDirectory(&value); if (NS_SUCCEEDED(rv) && value) { nsDirectoryService::gService->Set(NS_XPCOM_INIT_CURRENT_PROCESS_DIR, aBinDirectory); } } if (aAppFileLocationProvider) { rv = nsDirectoryService::gService->RegisterProvider(aAppFileLocationProvider); if (NS_FAILED(rv)) { return rv; } } nsCOMPtr<nsIFile> xpcomLib; nsDirectoryService::gService->Get(NS_GRE_BIN_DIR, NS_GET_IID(nsIFile), getter_AddRefs(xpcomLib)); MOZ_ASSERT(xpcomLib); // set gGREBinPath nsAutoString path; xpcomLib->GetPath(path); gGREBinPath = ToNewUnicode(path); xpcomLib->AppendNative(nsDependentCString(XPCOM_DLL)); nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib); if (!mozilla::Omnijar::IsInitialized()) { mozilla::Omnijar::Init(); } if ((sCommandLineWasInitialized = !CommandLine::IsInitialized())) { #ifdef OS_WIN CommandLine::Init(0, nullptr); #else nsCOMPtr<nsIFile> binaryFile; nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(binaryFile)); if (NS_WARN_IF(!binaryFile)) { return NS_ERROR_FAILURE; } rv = binaryFile->AppendNative(NS_LITERAL_CSTRING("nonexistent-executable")); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCString binaryPath; rv = binaryFile->GetNativePath(binaryPath); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } static char const* const argv = { strdup(binaryPath.get()) }; CommandLine::Init(1, &argv); #endif } NS_ASSERTION(nsComponentManagerImpl::gComponentManager == nullptr, "CompMgr not null at init"); // Create the Component/Service Manager nsComponentManagerImpl::gComponentManager = new nsComponentManagerImpl(); NS_ADDREF(nsComponentManagerImpl::gComponentManager); // Global cycle collector initialization. if (!nsCycleCollector_init()) { return NS_ERROR_UNEXPECTED; } // And start it up for this thread too. nsCycleCollector_startup(); // Register ICU memory functions. This really shouldn't be necessary: the // JS engine should do this on its own inside JS_Init, and memory-reporting // code should call a JSAPI function to observe ICU memory usage. But we // can't define the alloc/free functions in the JS engine, because it can't // depend on the XPCOM-based memory reporting goop. So for now, we have // this oddness. mozilla::SetICUMemoryFunctions(); // Do the same for libogg. ogg_set_mem_functions(OggReporter::CountingMalloc, OggReporter::CountingCalloc, OggReporter::CountingRealloc, OggReporter::CountingFree); #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING) // And for VPX. vpx_mem_set_functions(VPXReporter::CountingMalloc, VPXReporter::CountingCalloc, VPXReporter::CountingRealloc, VPXReporter::CountingFree, memcpy, memset, memmove); #endif #ifdef MOZ_WEBM // And for libnestegg. // libnestegg expects that its realloc implementation will free // the pointer argument when a size of 0 is passed in, so we need // the special version of the counting realloc. nestegg_set_halloc_func(NesteggReporter::CountingFreeingRealloc); #endif // Initialize the JS engine. if (!JS_Init()) { NS_RUNTIMEABORT("JS_Init failed"); } rv = nsComponentManagerImpl::gComponentManager->Init(); if (NS_FAILED(rv)) { NS_RELEASE(nsComponentManagerImpl::gComponentManager); return rv; } if (aResult) { NS_ADDREF(*aResult = nsComponentManagerImpl::gComponentManager); } // The iimanager constructor searches and registers XPT files. // (We trigger the singleton's lazy construction here to make that happen.) (void)XPTInterfaceInfoManager::GetSingleton(); // After autoreg, but before we actually instantiate any components, // add any services listed in the "xpcom-directory-providers" category // to the directory service. nsDirectoryService::gService->RegisterCategoryProviders(); // Init SharedThreadPool (which needs the service manager). SharedThreadPool::InitStatics(); // Init AbstractThread. AbstractThread::InitStatics(); // Force layout to spin up so that nsContentUtils is available for cx stack // munging. nsCOMPtr<nsISupports> componentLoader = do_GetService("@mozilla.org/moz/jsloader;1"); mozilla::scache::StartupCache::GetSingleton(); mozilla::AvailableMemoryTracker::Activate(); // Notify observers of xpcom autoregistration start NS_CreateServicesFromCategory(NS_XPCOM_STARTUP_CATEGORY, nullptr, NS_XPCOM_STARTUP_OBSERVER_ID); #ifdef XP_WIN CreateAnonTempFileRemover(); #endif // We only want the SystemMemoryReporter running in one process, because it // profiles the entire system. The main process is the obvious place for // it. if (XRE_IsParentProcess()) { mozilla::SystemMemoryReporter::Init(); } // The memory reporter manager is up and running -- register our reporters. RegisterStrongMemoryReporter(new ICUReporter()); RegisterStrongMemoryReporter(new OggReporter()); #ifdef MOZ_VPX RegisterStrongMemoryReporter(new VPXReporter()); #endif #ifdef MOZ_WEBM RegisterStrongMemoryReporter(new NesteggReporter()); #endif mozilla::Telemetry::Init(); mozilla::HangMonitor::Startup(); mozilla::BackgroundHangMonitor::Startup(); const MessageLoop* const loop = MessageLoop::current(); sMainHangMonitor = new mozilla::BackgroundHangMonitor( loop->thread_name().c_str(), loop->transient_hang_timeout(), loop->permanent_hang_timeout()); return NS_OK; }