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

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: Torne's comment addressed Created 4 years, 11 months 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 }
51
52 CrashMicroDumpManager::~CrashMicroDumpManager() {
53 instance_ = nullptr;
54 {
55 base::AutoLock auto_lock(child_process_id_to_pipe_fd_lock_);
56 for (const auto& iter : child_process_id_to_pipe_fd_) {
57 IGNORE_EINTR(close(iter.second));
58 }
59 }
60 }
61
62 base::File CrashMicroDumpManager::CreateCrashInfoChannel(int child_process_id) {
63 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
64 int local_pipe_fd = -1, child_pipe_fd = -1;
65 // IPC::SocketPair creates a pipe in non-blocking mode.
66 if (!IPC::SocketPair(&local_pipe_fd, &child_pipe_fd)) {
Robert Sesek 2016/01/05 15:58:45 Can you use base::SyncSocket instead of IPC::Socke
mnaganov (inactive) 2016/01/05 16:22:02 I guess, as we only write / read a couple of bytes
67 return base::File();
68 }
69 {
70 base::AutoLock auto_lock(child_process_id_to_pipe_fd_lock_);
71 DCHECK(!ContainsKey(child_process_id_to_pipe_fd_, child_process_id));
72 child_process_id_to_pipe_fd_[child_process_id] = local_pipe_fd;
73 }
74 return base::File(child_pipe_fd);
75 }
76
77 // static
78 void CrashMicroDumpManager::HandleChildTermination(
79 int pipe_fd,
80 base::TerminationStatus termination_status) {
81 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
82 CHECK(instance_);
83
84 base::ScopedFD pipe(pipe_fd);
85 if (termination_status == base::TERMINATION_STATUS_NORMAL_TERMINATION) {
86 // Just close our end of the pipe via ScopedFD.
87 return;
88 }
89 int exit_code;
90 ssize_t num_read = HANDLE_EINTR(read(pipe_fd, &exit_code, sizeof(exit_code)));
91 if (num_read <= 0) {
92 // The child process hasn't written anything into the pipe. This implies
93 // that it was terminated via SIGKILL by the low memory killer, and thus we
94 // need to perform a clean exit.
95 exit(0);
96 } else {
97 LOG(FATAL) << "Renderer process crash detected (code " << exit_code
98 << "). Terminating browser.";
99 }
100 }
101
102 void CrashMicroDumpManager::Observe(
103 int type,
104 const content::NotificationSource& source,
105 const content::NotificationDetails& details) {
106 content::RenderProcessHost* rph =
107 content::Source<content::RenderProcessHost>(source).ptr();
108 // In case of a normal termination we just need to close the pipe_fd we kept
109 // open.
110 base::TerminationStatus term_status =
111 base::TERMINATION_STATUS_NORMAL_TERMINATION;
112 switch (type) {
113 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
114 // NOTIFICATION_RENDERER_PROCESS_TERMINATED is sent when the renderer
115 // process is cleanly shutdown.
116 break;
117 }
118 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
119 // Android fast shutdowns is a known case where the renderer is
120 // intentionally killed when we are done with it.
121 if (!rph->FastShutdownStarted()) {
122 content::RenderProcessHost::RendererClosedDetails* process_details =
123 content::Details<content::RenderProcessHost::RendererClosedDetails>(
124 details).ptr();
125 term_status = process_details->status;
126 }
127 break;
128 }
129 default:
130 NOTREACHED();
131 return;
132 }
133 OnChildExit(rph->GetID(), term_status);
134 }
135
136 void CrashMicroDumpManager::OnChildExit(
137 int child_process_id,
138 base::TerminationStatus termination_status) {
139 int pipe_fd = -1;
140 {
141 base::AutoLock auto_lock(child_process_id_to_pipe_fd_lock_);
142 const auto& iter = child_process_id_to_pipe_fd_.find(child_process_id);
143 if (iter == child_process_id_to_pipe_fd_.end()) {
144 // We might get a NOTIFICATION_RENDERER_PROCESS_TERMINATED and a
145 // NOTIFICATION_RENDERER_PROCESS_CLOSED.
146 return;
147 }
148 pipe_fd = iter->second;
149 child_process_id_to_pipe_fd_.erase(iter);
150 }
151 DCHECK(pipe_fd != -1);
152 BrowserThread::PostTask(
153 BrowserThread::FILE, FROM_HERE,
154 base::Bind(&CrashMicroDumpManager::HandleChildTermination, pipe_fd,
155 termination_status));
156 }
157
158 } // namespace breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698