Move the TaskRunner for process launching to ChildProcessLauncherHelper.
ServiceManager may need to launch child processes before a BrowserMainLoop
has been created, and therefore before any BrowserThreads exists. We
therefore replace the BrowserThread::PROCESS_LAUNCHER with a global
TaskScheduler sequence, created on-demand when the ServiceManager or
ChildProcessLauncherHelper first need it.
Under Windows we must use a single-thread TaskRunner, while on other
platforms we are able to use a normal TaskScheduler sequence. File
crbug.com/820200 to track that.
Bug: 815225
Change-Id: Ia0f46461fb9cc92fddacf81ee96b764de8477d11
Reviewed-on: https://chromium-review.googlesource.com/941264
Commit-Queue: Xi Han <[email protected]>
Reviewed-by: Ken Rockot <[email protected]>
Reviewed-by: John Abd-El-Malek <[email protected]>
Reviewed-by: Wez <[email protected]>
Cr-Commit-Position: refs/heads/master@{#542212}
diff --git a/content/browser/child_process_launcher_helper.cc b/content/browser/child_process_launcher_helper.cc
index 7ee3df4..e924b12d 100644
--- a/content/browser/child_process_launcher_helper.cc
+++ b/content/browser/child_process_launcher_helper.cc
@@ -6,18 +6,28 @@
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
+#include "base/single_thread_task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/task_scheduler/single_thread_task_runner_thread_mode.h"
+#include "base/task_scheduler/task_traits.h"
#include "content/browser/child_process_launcher.h"
+#include "content/public/browser/child_process_launcher_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
+#if defined(OS_ANDROID)
+#include "content/browser/android/launcher_thread.h"
+#endif
+
namespace content {
namespace internal {
namespace {
void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
- DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+ DCHECK(CurrentlyOnProcessLauncherTaskRunner());
// Log the launch time, separating out the first one (which will likely be
// slower due to the rest of the browser initializing at the same time).
static bool done_first_launch = false;
@@ -85,14 +95,14 @@
mojo_client_handle_ = channel_pair.PassClientHandle();
}
- BrowserThread::PostTask(
- BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
+ GetProcessLauncherTaskRunner()->PostTask(
+ FROM_HERE,
base::BindOnce(&ChildProcessLauncherHelper::LaunchOnLauncherThread,
this));
}
void ChildProcessLauncherHelper::LaunchOnLauncherThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
+ DCHECK(CurrentlyOnProcessLauncherTaskRunner());
begin_launch_time_ = base::TimeTicks::Now();
@@ -167,18 +177,52 @@
// static
void ChildProcessLauncherHelper::ForceNormalProcessTerminationAsync(
ChildProcessLauncherHelper::Process process) {
- if (BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)) {
+ if (CurrentlyOnProcessLauncherTaskRunner()) {
ForceNormalProcessTerminationSync(std::move(process));
return;
}
// On Posix, EnsureProcessTerminated can lead to 2 seconds of sleep!
// So don't do this on the UI/IO threads.
- BrowserThread::PostTask(
- BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
+ GetProcessLauncherTaskRunner()->PostTask(
+ FROM_HERE,
base::BindOnce(
&ChildProcessLauncherHelper::ForceNormalProcessTerminationSync,
std::move(process)));
}
} // namespace internal
+
+// static
+base::SingleThreadTaskRunner* GetProcessLauncherTaskRunner() {
+#if defined(OS_ANDROID)
+ // Android specializes Launcher thread so it is accessible in java.
+ // Note Android never does clean shutdown, so shutdown use-after-free
+ // concerns are not a problem in practice.
+ // This process launcher thread will use the Java-side process-launching
+ // thread, instead of creating its own separate thread on C++ side. Note
+ // that means this thread will not be joined on shutdown, and may cause
+ // use-after-free if anything tries to access objects deleted by
+ // AtExitManager, such as non-leaky LazyInstance.
+ static base::NoDestructor<scoped_refptr<base::SingleThreadTaskRunner>>
+ launcher_task_runner(
+ android::LauncherThread::GetMessageLoop()->task_runner());
+#else // defined(OS_ANDROID)
+ constexpr base::TaskTraits task_traits = {
+ base::MayBlock(), base::WithBaseSyncPrimitives(),
+ base::TaskPriority::USER_BLOCKING,
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN};
+ // TODO(wez): Investigates whether we could use SequencedTaskRunner on
+ // platforms other than Windows. http://crbug.com/820200.
+ static base::NoDestructor<scoped_refptr<base::SingleThreadTaskRunner>>
+ launcher_task_runner(base::CreateSingleThreadTaskRunnerWithTraits(
+ task_traits, base::SingleThreadTaskRunnerThreadMode::DEDICATED));
+#endif // defined(OS_ANDROID)
+ return (*launcher_task_runner).get();
+}
+
+// static
+bool CurrentlyOnProcessLauncherTaskRunner() {
+ return GetProcessLauncherTaskRunner()->RunsTasksInCurrentSequence();
+}
+
} // namespace content