blob: f734fb86e0dbb03a3afcffad66a8d54af2d87a01 [file]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_HEAP_PROFILING_MULTI_PROCESS_SUPERVISOR_H_
#define COMPONENTS_HEAP_PROFILING_MULTI_PROCESS_SUPERVISOR_H_
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
#include "base/process/process.h"
#include "base/thread_annotations.h"
#include "base/threading/thread_checker.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
#include "components/services/heap_profiling/public/mojom/heap_profiling_service.mojom.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
namespace heap_profiling {
class ClientConnectionManager;
class Controller;
enum class Mode;
// This class presents a single interface for both tests and embedders to use
// the HeapProfilingService. This class is intended to be used from the
// browser/privileged process of the embedder.
//
// This class must be accessed from the UI thread.
//
// Internally, this class:
// * Starts the HeapProfilingService.
// * Hooks up all the connections so that the appropriate processes get
// profiled.
class Supervisor {
public:
static Supervisor* GetInstance();
Supervisor(const Supervisor&) = delete;
Supervisor& operator=(const Supervisor&) = delete;
// When this returns |false|, no method other than Start() or
// SetClientConnectionManagerConstructor() can be called.
bool HasStarted();
// Embedders can use this method to force the Supervisor to instantiate a
// ClientConnectionManager subclass during Start(). The function will be
// called on the UI thread.
using ClientConnectionManagerConstructor =
std::unique_ptr<ClientConnectionManager> (*)(
base::WeakPtr<Controller> controller_weak_ptr,
Mode mode);
void SetClientConnectionManagerConstructor(
ClientConnectionManagerConstructor constructor);
// Must be called at most once.
// The first method is a convenience method that calls the second with
// default parameters.
// Start is an asynchronous operation that must hop to the IO thread and then
// back to the UI thread. |callback| will be invoked on the UI thread after
// this is finished.
//
// This is a brief period of time when this object is in a semi-initialized
// state - when Start has been called, but the thread hops haven't finished.
// We avoid this side case by:
// * Providing a |callback| for callers to use, if they need to do anything
// shortly after Start().
// * Relying on the assumption that in all other cases, the object is either
// fully initialized or not initialized. There are DCHECKs to enforce this
// assumption.
void Start(base::OnceClosure callback);
void Start(Mode mode,
mojom::StackMode stack_mode,
uint32_t sampling_rate,
base::OnceClosure callback);
// Stops profiling in all connected clients and tears down the supervisor
// process-wide state. |callback| is invoked on the UI thread with a boolean
// indicating whether profiling was successfully stopped.
void Stop(base::OnceCallback<void(bool)> callback);
Mode GetMode();
// Starts profiling the process with the given `pid`. Invokes
// `started_profiling_closure` if and when profiling starts successfully.
void StartManualProfiling(base::ProcessId pid,
mojom::ProfilingService::AddProfilingClientCallback
started_profiling_closure);
// Returns the pids of all profiled processes. The callback is posted on the
// UI thread.
using GetProfiledPidsCallback =
base::OnceCallback<void(std::vector<base::ProcessId> pids)>;
void GetProfiledPids(GetProfiledPidsCallback callback);
uint32_t GetSamplingRate();
using TraceFinishedCallback =
base::OnceCallback<void(bool success, std::string trace_json)>;
// This method must be called from the UI thread. |callback| will be called
// asynchronously on the UI thread.
//
// This function does the following:
// 1. Starts tracing with no categories enabled.
// 2. Requests and waits for memory_instrumentation service to dump to
// trace.
// 3. Stops tracing.
void RequestTraceWithHeapDump(TraceFinishedCallback callback, bool anonymize);
private:
friend class base::NoDestructor<Supervisor>;
Supervisor();
~Supervisor();
// Initialization stage 1: Register with the MemoryInstrumentationRegistry.
// `continue_on_io_thread` is a callback to the next stage, which must be
// bound to the IO thread.
void RegisterProfilerOnMemoryInfraThread(
base::OnceCallback<void(
mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>,
mojo::PendingRemote<
memory_instrumentation::mojom::HeapProfilerHelper>)>
continue_on_io_thread);
// Initialization stage 2: Launch the Service on the IO thread.
// `continue_on_ui_thread` is a callback to the next stage, which must be
// bound to the UI thread.
void LaunchServiceOnIOThread(
mojom::StackMode stack_mode,
uint32_t sampling_rate,
base::OnceCallback<void(base::WeakPtr<Controller>)> continue_on_ui_thread,
mojo::PendingReceiver<memory_instrumentation::mojom::HeapProfiler>
receiver,
mojo::PendingRemote<memory_instrumentation::mojom::HeapProfilerHelper>
remote_helper);
// Initialization stage 3: Save controller pointer and start the
// ClientConnectionManager.
void ControllerStartedOnUIThread(
Mode mode,
base::OnceClosure closure,
base::WeakPtr<Controller> controller_weak_ptr);
// Starts the ClientConnectionManager. Can be called multiple times.
void StartClientConnectionOnUIThread(Mode mode, base::OnceClosure closure);
void GetProfiledPidsOnIOThread(GetProfiledPidsCallback callback);
void StopOnIOThread(base::OnceCallback<void(bool)> callback);
// Bound to the IO thread.
std::unique_ptr<Controller> controller_;
THREAD_CHECKER(ui_thread_checker_);
// Bound to the UI thread.
std::unique_ptr<ClientConnectionManager> client_connection_manager_
GUARDED_BY_CONTEXT(ui_thread_checker_);
base::WeakPtr<Controller> controller_weak_ptr_
GUARDED_BY_CONTEXT(ui_thread_checker_);
ClientConnectionManagerConstructor constructor_ = nullptr;
bool started_ GUARDED_BY_CONTEXT(ui_thread_checker_) = false;
enum class InitializationState {
kNotInitialized,
kInitializing,
kInitialized
};
InitializationState initialization_state_ GUARDED_BY_CONTEXT(
ui_thread_checker_) = InitializationState::kNotInitialized;
};
} // namespace heap_profiling
#endif // COMPONENTS_HEAP_PROFILING_MULTI_PROCESS_SUPERVISOR_H_