| // Copyright 2015 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_CRASH_CONTENT_BROWSER_CHILD_EXIT_OBSERVER_ANDROID_H_ |
| #define COMPONENTS_CRASH_CONTENT_BROWSER_CHILD_EXIT_OBSERVER_ANDROID_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <vector> |
| |
| #include "base/android/application_status_listener.h" |
| #include "base/android/child_process_binding_types.h" |
| #include "base/process/process.h" |
| #include "base/scoped_multi_source_observation.h" |
| #include "base/scoped_observation.h" |
| #include "base/synchronization/lock.h" |
| #include "components/crash/content/browser/crash_handler_host_linux.h" |
| #include "content/public/browser/browser_child_process_observer.h" |
| #include "content/public/browser/child_process_host.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_process_host_creation_observer.h" |
| #include "content/public/browser/render_process_host_observer.h" |
| #include "content/public/common/process_type.h" |
| #include "third_party/blink/public/common/oom_intervention/oom_intervention_types.h" |
| |
| namespace content { |
| struct ChildProcessTerminationInfo; |
| } |
| |
| namespace crash_reporter { |
| |
| // This class centralises the observation of child processes for the |
| // purpose of reacting to child process crashes. |
| // The ChildExitObserver instance exists on the browser main thread. |
| class ChildExitObserver : public content::BrowserChildProcessObserver, |
| public content::RenderProcessHostCreationObserver, |
| public content::RenderProcessHostObserver, |
| public crashpad::CrashHandlerHost::Observer { |
| public: |
| struct TerminationInfo { |
| // Used to indicate the child did not receive a crash signal. |
| static constexpr int kInvalidSigno = -1; |
| |
| TerminationInfo(); |
| TerminationInfo(const TerminationInfo& other); |
| TerminationInfo& operator=(const TerminationInfo& other); |
| |
| bool is_crashed() const { |
| return crash_signo != kInvalidSigno || threw_exception_during_init; |
| } |
| |
| int process_host_id = content::ChildProcessHost::kInvalidUniqueID; |
| // |pid| may not be valid if termination happens before the process has |
| // finished launching. |
| base::ProcessHandle pid = base::kNullProcessHandle; |
| content::ProcessType process_type = content::PROCESS_TYPE_UNKNOWN; |
| base::android::ApplicationState app_state = |
| base::android::APPLICATION_STATE_UNKNOWN; |
| |
| // The crash signal the child process received before it exited. |
| int crash_signo = kInvalidSigno; |
| |
| // True if this is intentional shutdown of the child process, e.g. when a |
| // tab is closed. Some fields below may not be populated if this is true. |
| bool normal_termination = false; |
| |
| // Renderer process shutdown started by RenderProcessHost::Shutdown. |
| bool renderer_shutdown_requested = false; |
| |
| // Values from ChildProcessTerminationInfo. |
| // Note base::TerminationStatus and exit_code are missing intentionally |
| // because those fields hold no useful information on Android. |
| base::android::ChildBindingState binding_state = |
| base::android::ChildBindingState::UNBOUND; |
| bool threw_exception_during_init = false; |
| bool was_killed_intentionally_by_browser = false; |
| |
| // Applies to renderer process only. Generally means renderer is hosting |
| // one or more visible tabs. |
| bool renderer_has_visible_clients = false; |
| |
| // Applies to renderer process only. Generally true indicates that there |
| // is no main frame being hosted in this renderer process. Note there are |
| // edge cases, eg if an invisible main frame and a visible sub frame from |
| // different tabs are sharing the same renderer, then this is false. |
| bool renderer_was_subframe = false; |
| |
| // Applies to renderer process only. This metrics contains the information |
| // about virtual address space OOM situation, private memory footprint, |
| // swap size, vm size and the estimation of blink memory usage. |
| blink::OomInterventionMetrics blink_oom_metrics; |
| |
| // Applies to renderer process only. Whether the killed process is a |
| // spare renderer. |
| bool is_spare_renderer = false; |
| |
| // Applies to renderer process only. Whether there is any spare renderer |
| // in the browser when the process is killed. Always true if the killed |
| // process is a spare renderer. |
| bool has_spare_renderer = false; |
| }; |
| |
| // ChildExitObserver client interface. |
| // Client methods will be called synchronously in the order in which |
| // clients were registered. It is the implementer's responsibility |
| // to post tasks to the appropriate threads if required (and be |
| // aware that this may break ordering guarantees). |
| // |
| // Note, callbacks are generated for both "child processes" which are hosted |
| // by BrowserChildProcessHosts, and "render processes" which are hosted by |
| // RenderProcessHosts. The unique ids correspond to either the |
| // ChildProcessData::id, or the RenderProcessHost::ID, depending on the |
| // process type. |
| class Client { |
| public: |
| // OnChildExit is called on the UI thread. |
| // OnChildExit may be called twice for the same process. |
| virtual void OnChildExit(const TerminationInfo& info) = 0; |
| |
| virtual ~Client() = default; |
| }; |
| ChildExitObserver(); |
| ~ChildExitObserver() override; |
| |
| ChildExitObserver(const ChildExitObserver&) = delete; |
| ChildExitObserver& operator=(const ChildExitObserver&) = delete; |
| |
| void RegisterClient(std::unique_ptr<Client> client); |
| |
| // crashpad::CrashHandlerHost::Observer |
| void ChildReceivedCrashSignal(base::ProcessId pid, int signo) override; |
| |
| // content::RenderProcessHostCreationObserver implementation. |
| void OnRenderProcessHostCreated(content::RenderProcessHost* host) override; |
| |
| private: |
| // content::BrowserChildProcessObserver implementation: |
| void BrowserChildProcessHostDisconnected( |
| const content::ChildProcessData& data) override; |
| void BrowserChildProcessKilled( |
| const content::ChildProcessData& data, |
| const content::ChildProcessTerminationInfo& info) override; |
| |
| // RenderProcessHostObserver implementation. |
| // RenderProcessHostDestroyed() corresponds to death of an underlying |
| // RenderProcess. RenderProcessExited() corresponds to when the |
| // RenderProcessHost's lifetime is ending. Ideally, we'd only listen to the |
| // former, but if the RenderProcessHost is destroyed before the RenderProcess, |
| // then the former is never observed. |
| void RenderProcessExited( |
| content::RenderProcessHost* host, |
| const content::ChildProcessTerminationInfo& info) override; |
| void RenderProcessHostDestroyed(content::RenderProcessHost* host) override; |
| |
| // Processes RenderProcessHost exited and destroyed events. |content_info| is |
| // expected to be null for destroyed events. |
| void ProcessRenderProcessHostLifetimeEndEvent( |
| content::RenderProcessHost* rph, |
| const content::ChildProcessTerminationInfo* content_info); |
| |
| // Called on child process exit (including crash). |
| void OnChildExit(TerminationInfo* info); |
| |
| base::Lock registered_clients_lock_; |
| std::vector<std::unique_ptr<Client>> registered_clients_; |
| |
| // process_host_id to process id. Only accessed on the UI thread. |
| std::map<int, base::ProcessHandle> process_host_id_to_pid_; |
| |
| // Key is process_host_id. Only used for BrowserChildProcessHost. Only |
| // accessed on the UI thread. |
| std::map<int, TerminationInfo> browser_child_process_info_; |
| |
| base::ScopedMultiSourceObservation<content::RenderProcessHost, |
| content::RenderProcessHostObserver> |
| render_process_host_observation_{this}; |
| |
| base::Lock crash_signals_lock_; |
| std::map<base::ProcessId, int> child_pid_to_crash_signal_; |
| base::ScopedObservation<crashpad::CrashHandlerHost, |
| crashpad::CrashHandlerHost::Observer> |
| scoped_crash_handler_host_observation_{this}; |
| }; |
| |
| } // namespace crash_reporter |
| |
| #endif // COMPONENTS_CRASH_CONTENT_BROWSER_CHILD_EXIT_OBSERVER_ANDROID_H_ |