Commit f552e983 authored by Sebastien Marchand's avatar Sebastien Marchand Committed by Commit Bot

Wait for all child processes to dump their profiling data on shutdown

This only affects profiling builds (coverage or PGO)

There's already some logic to wait for all the renderer processes to
dump their profiling data on shutdown but this doesn't cover the utility
processes and they end up corrupting some profile data files. This CL
extends the logic that we already use for the renderer and GPU processes
to the other childs.

Bug: 1071664, 1124774
Change-Id: I64a1fa247226a3521efc6680bb103c15f7b37cc0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2399819Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Sébastien Marchand <sebmarchand@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805460}
parent b199e9bc
...@@ -71,6 +71,9 @@ ...@@ -71,6 +71,9 @@
#endif #endif
#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_utils.h" #include "content/public/browser/gpu_utils.h"
#include "content/public/common/profiling_utils.h" #include "content/public/common/profiling_utils.h"
#endif #endif
...@@ -157,6 +160,27 @@ void OnShutdownStarting(ShutdownType type) { ...@@ -157,6 +160,27 @@ void OnShutdownStarting(ShutdownType type) {
base::Unretained(wait_for_profiling_data.GetNewWaitableEvent()))); base::Unretained(wait_for_profiling_data.GetNewWaitableEvent())));
} }
// Ask all the other child processes to dump their profiling data, this has
// to be done on the IO thread.
content::GetIOThreadTaskRunner({})->PostTaskAndReply(
FROM_HERE, base::BindOnce([]() {
// Use a nested WaitForProcessesToDumpProfilingInfo object to wait on
// the IO thread.
content::WaitForProcessesToDumpProfilingInfo
nested_wait_for_profiling_data;
for (content::BrowserChildProcessHostIterator browser_child_iter;
!browser_child_iter.Done(); ++browser_child_iter) {
browser_child_iter.GetHost()->DumpProfilingData(base::BindOnce(
&base::WaitableEvent::Signal,
base::Unretained(
nested_wait_for_profiling_data.GetNewWaitableEvent())));
}
nested_wait_for_profiling_data.WaitForAll();
}),
base::BindOnce(
&base::WaitableEvent::Signal,
base::Unretained(wait_for_profiling_data.GetNewWaitableEvent())));
if (!base::CommandLine::ForCurrentProcess()->HasSwitch( if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kInProcessGPU)) { switches::kInProcessGPU)) {
content::DumpGpuProfilingData(base::BindOnce( content::DumpGpuProfilingData(base::BindOnce(
...@@ -168,7 +192,7 @@ void OnShutdownStarting(ShutdownType type) { ...@@ -168,7 +192,7 @@ void OnShutdownStarting(ShutdownType type) {
// data to disk. // data to disk.
wait_for_profiling_data.WaitForAll(); wait_for_profiling_data.WaitForAll();
} }
#endif // defined(OS_WIN) && BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) #endif // BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) && BUILDFLAG(CLANG_PGO)
// Call FastShutdown on all of the RenderProcessHosts. This will be // Call FastShutdown on all of the RenderProcessHosts. This will be
// a no-op in some cases, so we still need to go through the normal // a no-op in some cases, so we still need to go through the normal
......
...@@ -89,6 +89,7 @@ ...@@ -89,6 +89,7 @@
#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX) #if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
#include <stdio.h> #include <stdio.h>
#include "base/test/clang_profiling.h"
#if defined(OS_WIN) #if defined(OS_WIN)
#include <io.h> #include <io.h>
#endif #endif
...@@ -380,6 +381,12 @@ class ChildThreadImpl::IOThreadState ...@@ -380,6 +381,12 @@ class ChildThreadImpl::IOThreadState
__llvm_profile_set_file_object(f, 1); __llvm_profile_set_file_object(f, 1);
#endif #endif
} }
void WriteClangProfilingProfile(
WriteClangProfilingProfileCallback callback) override {
base::WriteClangProfilingProfile();
std::move(callback).Run();
}
#endif #endif
const scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_; const scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
......
...@@ -74,4 +74,9 @@ interface ChildProcess { ...@@ -74,4 +74,9 @@ interface ChildProcess {
// Used for the coverage builds. // Used for the coverage builds.
[EnableIf=clang_profiling_inside_sandbox] [EnableIf=clang_profiling_inside_sandbox]
SetProfilingFile(mojo_base.mojom.File file); SetProfilingFile(mojo_base.mojom.File file);
// Write out the accumulated code profiling profile to the configured file.
// The callback is invoked once the profile has been flushed to disk.
[EnableIf=clang_profiling_inside_sandbox]
WriteClangProfilingProfile() => ();
}; };
...@@ -333,4 +333,10 @@ void ChildProcessHostImpl::OnBadMessageReceived(const IPC::Message& message) { ...@@ -333,4 +333,10 @@ void ChildProcessHostImpl::OnBadMessageReceived(const IPC::Message& message) {
delegate_->OnBadMessageReceived(message); delegate_->OnBadMessageReceived(message);
} }
#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
void ChildProcessHostImpl::DumpProfilingData(base::OnceClosure callback) {
child_process_->WriteClangProfilingProfile(std::move(callback));
}
#endif
} // namespace content } // namespace content
...@@ -100,6 +100,10 @@ class CONTENT_EXPORT ChildProcessHostImpl ...@@ -100,6 +100,10 @@ class CONTENT_EXPORT ChildProcessHostImpl
// non-null. // non-null.
bool InitChannel(); bool InitChannel();
#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
void DumpProfilingData(base::OnceClosure callback) override;
#endif
// The outgoing Mojo invitation which must be consumed to bootstrap Mojo IPC // The outgoing Mojo invitation which must be consumed to bootstrap Mojo IPC
// to the child process. // to the child process.
base::Optional<mojo::OutgoingInvitation> mojo_invitation_{base::in_place}; base::Optional<mojo::OutgoingInvitation> mojo_invitation_{base::in_place};
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/clang_profiling_buildflags.h"
#include "base/files/scoped_file.h" #include "base/files/scoped_file.h"
#include "base/optional.h" #include "base/optional.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -167,6 +168,12 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Sender { ...@@ -167,6 +168,12 @@ class CONTENT_EXPORT ChildProcessHost : public IPC::Sender {
virtual void RunService( virtual void RunService(
const std::string& service_name, const std::string& service_name,
mojo::PendingReceiver<service_manager::mojom::Service> receiver) = 0; mojo::PendingReceiver<service_manager::mojom::Service> receiver) = 0;
#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
// Write out the accumulated code profiling profile to the configured file.
// The callback is invoked once the profile has been flushed to disk.
virtual void DumpProfilingData(base::OnceClosure callback) = 0;
#endif
}; };
} // namespace content } // namespace content
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment