Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: components/crash/content/browser/crash_micro_dump_manager_android.cc

Issue 1525023003: Distinguish in the browser between renderer crashes and kills (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Implemented detection of a volunatry renderer exit Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/crash/content/browser/crash_micro_dump_manager_android.h"
6
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <sys/socket.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include "base/bind.h"
14 #include "base/files/scoped_file.h"
15 #include "base/logging.h"
16 #include "base/posix/eintr_wrapper.h"
17 #include "base/stl_util.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/child_process_data.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/notification_types.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "ipc/ipc_channel.h"
24
25 using content::BrowserThread;
26
27 namespace breakpad {
28
29 // static
30 CrashMicroDumpManager* CrashMicroDumpManager::instance_ = nullptr;
31
32 // static
33 CrashMicroDumpManager* CrashMicroDumpManager::GetInstance() {
34 CHECK(instance_);
35 return instance_;
36 }
37
38 CrashMicroDumpManager::CrashMicroDumpManager() {
39 DCHECK_CURRENTLY_ON(BrowserThread::UI);
40 DCHECK(!instance_);
41
42 instance_ = this;
43
44 notification_registrar_.Add(this,
45 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
46 content::NotificationService::AllSources());
47 notification_registrar_.Add(this,
48 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
49 content::NotificationService::AllSources());
50 BrowserChildProcessObserver::Add(this);
51 }
52
53 CrashMicroDumpManager::~CrashMicroDumpManager() {
54 instance_ = nullptr;
55 BrowserChildProcessObserver::Remove(this);
56 {
57 base::AutoLock auto_lock(child_process_id_to_pipe_fd_lock_);
58 for (const auto& iter : child_process_id_to_pipe_fd_) {
59 IGNORE_EINTR(close(iter.second));
60 }
61 }
62 }
63
64 base::File CrashMicroDumpManager::CreateCrashInfoChannel(int child_process_id) {
65 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
66 int local_pipe_fd = -1, child_pipe_fd = -1;
67 // IPC::SocketPair creates a pipe in non-blocking mode.
68 if (!IPC::SocketPair(&local_pipe_fd, &child_pipe_fd)) {
69 return base::File();
70 }
71 {
72 base::AutoLock auto_lock(child_process_id_to_pipe_fd_lock_);
73 DCHECK(!ContainsKey(child_process_id_to_pipe_fd_, child_process_id));
74 child_process_id_to_pipe_fd_[child_process_id] = local_pipe_fd;
75 }
76 return base::File(child_pipe_fd);
77 }
78
79 // static
80 void CrashMicroDumpManager::HandleChildTermination(
81 int pipe_fd,
82 base::TerminationStatus termination_status) {
83 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
84 CHECK(instance_);
85
86 base::ScopedFD pipe(pipe_fd);
Peter Wen 2015/12/17 16:47:10 nit: not necessary here, can move further down if
mnaganov (inactive) 2015/12/17 17:30:30 It's necessary to close the pipe fd in the case if
87 if (termination_status == base::TERMINATION_STATUS_NORMAL_TERMINATION) {
88 // Just close our end of the pipe via ScopedFD.
89 return;
90 }
91 int exit_code;
92 ssize_t num_read = HANDLE_EINTR(read(pipe_fd, &exit_code, sizeof(exit_code)));
93 if (num_read <= 0) {
94 // The child process hasn't written anything into the pipe. Assuming
95 // that it didn't crash, thus we need to perform a clean exit.
Peter Wen 2015/12/17 16:47:09 Please add the implied OOM SIGKILL to be clear for
mnaganov (inactive) 2015/12/17 17:30:30 Done.
96 exit(0);
97 } else {
98 LOG(FATAL) << "Renderer process crash detected. Terminating browser.";
99 }
100 }
101
102 void CrashMicroDumpManager::BrowserChildProcessHostDisconnected(
Peter Wen 2015/12/17 16:47:09 Same as above, are these necessary in webview?
mnaganov (inactive) 2015/12/17 17:30:30 You are right. I missed the comment on BrowserChil
103 const content::ChildProcessData& data) {
104 LOG(WARNING) << "WebView: BrowserChildProcessHostDisconnected!";
105 OnChildExit(data.id, base::TERMINATION_STATUS_MAX_ENUM);
106 }
107
108 void CrashMicroDumpManager::BrowserChildProcessCrashed(
109 const content::ChildProcessData& data,
110 int exit_code) {
111 LOG(WARNING) << "WebView: BrowserChildProcessCrashed!";
112 OnChildExit(data.id, base::TERMINATION_STATUS_ABNORMAL_TERMINATION);
113 }
114
115 void CrashMicroDumpManager::Observe(
116 int type,
117 const content::NotificationSource& source,
118 const content::NotificationDetails& details) {
119 content::RenderProcessHost* rph =
120 content::Source<content::RenderProcessHost>(source).ptr();
121 base::TerminationStatus term_status = base::TERMINATION_STATUS_MAX_ENUM;
122 switch (type) {
123 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
124 // NOTIFICATION_RENDERER_PROCESS_TERMINATED is sent when the renderer
125 // process is cleanly shutdown. However, we still need to close the
126 // minidump_fd we kept open.
Peter Wen 2015/12/17 16:47:09 Old comments. :)
mnaganov (inactive) 2015/12/17 17:30:30 Changed to pipe_fd. Thanks!
127 term_status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
128 break;
129 }
130 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
131 // We do not care about android fast shutdowns as it is a known case where
132 // the renderer is intentionally killed when we are done with it.
133 if (rph->FastShutdownStarted()) {
Peter Wen 2015/12/17 16:47:09 Does webview use fast shutdown? If so this may res
mnaganov (inactive) 2015/12/17 17:30:30 Good point -- we forgot to update the code in our
134 break;
135 }
136 content::RenderProcessHost::RendererClosedDetails* process_details =
137 content::Details<content::RenderProcessHost::RendererClosedDetails>(
138 details).ptr();
139 term_status = process_details->status;
140 break;
141 }
142 default:
143 NOTREACHED();
144 return;
145 }
146 OnChildExit(rph->GetID(), term_status);
147 }
148
149 void CrashMicroDumpManager::OnChildExit(
150 int child_process_id,
151 base::TerminationStatus termination_status) {
152 int pipe_fd = -1;
153 {
154 base::AutoLock auto_lock(child_process_id_to_pipe_fd_lock_);
155 const auto& iter = child_process_id_to_pipe_fd_.find(child_process_id);
156 if (iter == child_process_id_to_pipe_fd_.end()) {
157 // We might get a NOTIFICATION_RENDERER_PROCESS_TERMINATED and a
158 // NOTIFICATION_RENDERER_PROCESS_CLOSED.
159 return;
160 }
161 pipe_fd = iter->second;
162 child_process_id_to_pipe_fd_.erase(iter);
163 }
164 DCHECK(pipe_fd != -1);
165 BrowserThread::PostTask(
166 BrowserThread::FILE, FROM_HERE,
167 base::Bind(&CrashMicroDumpManager::HandleChildTermination, pipe_fd,
168 termination_status));
169 }
170
171 } // namespace breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698