diff --git a/dom/ipc/PreallocatedProcessManager.cpp b/dom/ipc/PreallocatedProcessManager.cpp index 02cd433acc2..eda2bc5bd50 100644 --- a/dom/ipc/PreallocatedProcessManager.cpp +++ b/dom/ipc/PreallocatedProcessManager.cpp @@ -92,6 +92,47 @@ private: bool mEnabled; bool mShutdown; nsRefPtr mPreallocatedAppProcess; + +#if defined(MOZ_NUWA_PROCESS) && defined(ENABLE_TESTS) + // For testing NS_NewUnmonitoredThread(). + + void CreateUnmonitoredThread(); + void DestroyUnmonitoredThread(); + + class UnmonitoredThreadRunnable : public nsRunnable + { + public: + UnmonitoredThreadRunnable() + : mMonitor("UnmonitoredThreadRunnable") + , mEnabled(true) + { } + + NS_IMETHODIMP Run() override + { + MonitorAutoLock mon(mMonitor); + while (mEnabled) { + mMonitor.Wait(); + } + return NS_OK; + } + + void Disable() + { + MonitorAutoLock mon(mMonitor); + mEnabled = false; + mMonitor.NotifyAll(); + } + + private: + ~UnmonitoredThreadRunnable() { } + + Monitor mMonitor; + bool mEnabled; + }; + + nsCOMPtr mUnmonitoredThread; + nsRefPtr mUnmonitoredThreadRunnable; +#endif }; /* static */ StaticRefPtr @@ -155,6 +196,40 @@ PreallocatedProcessManagerImpl::Observe(nsISupports* aSubject, return NS_OK; } +#if defined(MOZ_NUWA_PROCESS) && defined(ENABLE_TESTS) +void +PreallocatedProcessManagerImpl::CreateUnmonitoredThread() +{ + if (Preferences::GetBool("dom.ipc.newUnmonitoredThread.testMode")) { + // Create an unmonitored thread and dispatch a blocking runnable in test + // case startup. + nsresult rv = NS_NewUnmonitoredThread(getter_AddRefs(mUnmonitoredThread), + nullptr); + NS_ENSURE_SUCCESS_VOID(rv); + + mUnmonitoredThreadRunnable = new UnmonitoredThreadRunnable(); + mUnmonitoredThread->Dispatch(mUnmonitoredThreadRunnable, + NS_DISPATCH_NORMAL); + } +} + +void +PreallocatedProcessManagerImpl::DestroyUnmonitoredThread() +{ + // Cleanup after the test case finishes. + if (mUnmonitoredThreadRunnable) { + mUnmonitoredThreadRunnable->Disable(); + } + + if (mUnmonitoredThread) { + mUnmonitoredThread->Shutdown(); + } + + mUnmonitoredThreadRunnable = nullptr; + mUnmonitoredThread = nullptr; +} +#endif + void PreallocatedProcessManagerImpl::RereadPrefs() { @@ -180,6 +255,11 @@ PreallocatedProcessManagerImpl::Enable() mEnabled = true; #ifdef MOZ_NUWA_PROCESS +#ifdef ENABLE_TESTS + // For testing New_UnmonitoredThread(). + CreateUnmonitoredThread(); +#endif + ScheduleDelayedNuwaFork(); #else AllocateAfterDelay(); @@ -372,6 +452,11 @@ PreallocatedProcessManagerImpl::Disable() mEnabled = false; #ifdef MOZ_NUWA_PROCESS +#ifdef ENABLE_TESTS + // Shut down the test-only unmonitored thread. + DestroyUnmonitoredThread(); +#endif + // Cancel pending fork. if (mPreallocateAppProcessTask) { mPreallocateAppProcessTask->Cancel(); diff --git a/dom/ipc/tests/mochitest.ini b/dom/ipc/tests/mochitest.ini index 52780cc5dcf..067e24279a7 100644 --- a/dom/ipc/tests/mochitest.ini +++ b/dom/ipc/tests/mochitest.ini @@ -17,6 +17,8 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' skip-if = toolkit != 'gonk' [test_NuwaProcessDeadlock.html] skip-if = toolkit != 'gonk' +[test_NewUnmonitoredThread.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_NewUnmonitoredThread.html b/dom/ipc/tests/test_NewUnmonitoredThread.html new file mode 100644 index 00000000000..c52a45a3fce --- /dev/null +++ b/dom/ipc/tests/test_NewUnmonitoredThread.html @@ -0,0 +1,80 @@ + + + + + + + + + + + +