OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/android/crash_dump_manager.h" | 5 #include "chrome/browser/android/crash_dump_manager.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 DCHECK(!instance_); | 38 DCHECK(!instance_); |
39 | 39 |
40 instance_ = this; | 40 instance_ = this; |
41 | 41 |
42 notification_registrar_.Add(this, | 42 notification_registrar_.Add(this, |
43 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 43 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
44 content::NotificationService::AllSources()); | 44 content::NotificationService::AllSources()); |
45 notification_registrar_.Add(this, | 45 notification_registrar_.Add(this, |
46 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 46 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
47 content::NotificationService::AllSources()); | 47 content::NotificationService::AllSources()); |
48 notification_registrar_.Add(this, | 48 |
49 content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED, | 49 BrowserChildProcessObserver::Add(this); |
50 content::NotificationService::AllSources()); | |
51 notification_registrar_.Add(this, | |
52 content::NOTIFICATION_CHILD_PROCESS_CRASHED, | |
53 content::NotificationService::AllSources()); | |
54 } | 50 } |
55 | 51 |
56 CrashDumpManager::~CrashDumpManager() { | 52 CrashDumpManager::~CrashDumpManager() { |
57 instance_ = NULL; | 53 instance_ = NULL; |
| 54 |
| 55 BrowserChildProcessObserver::Remove(this); |
58 } | 56 } |
59 | 57 |
60 int CrashDumpManager::CreateMinidumpFile(int child_process_id) { | 58 int CrashDumpManager::CreateMinidumpFile(int child_process_id) { |
61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)); | 59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)); |
62 base::FilePath minidump_path; | 60 base::FilePath minidump_path; |
63 if (!file_util::CreateTemporaryFile(&minidump_path)) | 61 if (!file_util::CreateTemporaryFile(&minidump_path)) |
64 return base::kInvalidPlatformFileValue; | 62 return base::kInvalidPlatformFileValue; |
65 | 63 |
66 base::PlatformFileError error; | 64 base::PlatformFileError error; |
67 // We need read permission as the minidump is generated in several phases | 65 // We need read permission as the minidump is generated in several phases |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 if (!r) { | 115 if (!r) { |
118 LOG(ERROR) << "Failed to move crash dump from " << minidump_path.value() | 116 LOG(ERROR) << "Failed to move crash dump from " << minidump_path.value() |
119 << " to " << dest_path.value(); | 117 << " to " << dest_path.value(); |
120 file_util::Delete(minidump_path, false); | 118 file_util::Delete(minidump_path, false); |
121 return; | 119 return; |
122 } | 120 } |
123 LOG(INFO) << "Crash minidump successfully generated: " << | 121 LOG(INFO) << "Crash minidump successfully generated: " << |
124 crash_dump_dir.Append(filename).value(); | 122 crash_dump_dir.Append(filename).value(); |
125 } | 123 } |
126 | 124 |
| 125 void CrashDumpManager::BrowserChildProcessHostDisconnected( |
| 126 const content::ChildProcessData& data) { |
| 127 OnChildExit(data.id, data.handle); |
| 128 } |
| 129 |
| 130 void CrashDumpManager::BrowserChildProcessCrashed( |
| 131 const content::ChildProcessData& data) { |
| 132 OnChildExit(data.id, data.handle); |
| 133 } |
| 134 |
127 void CrashDumpManager::Observe(int type, | 135 void CrashDumpManager::Observe(int type, |
128 const content::NotificationSource& source, | 136 const content::NotificationSource& source, |
129 const content::NotificationDetails& details) { | 137 const content::NotificationDetails& details) { |
130 int child_process_id; | |
131 base::ProcessHandle pid; | |
132 switch (type) { | 138 switch (type) { |
133 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: | 139 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: |
134 // NOTIFICATION_RENDERER_PROCESS_TERMINATED is sent when the renderer | 140 // NOTIFICATION_RENDERER_PROCESS_TERMINATED is sent when the renderer |
135 // process is cleanly shutdown. However, we need to fallthrough so that | 141 // process is cleanly shutdown. However, we need to fallthrough so that |
136 // we close the minidump_fd we kept open. | 142 // we close the minidump_fd we kept open. |
137 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | 143 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { |
138 content::RenderProcessHost* rph = | 144 content::RenderProcessHost* rph = |
139 content::Source<content::RenderProcessHost>(source).ptr(); | 145 content::Source<content::RenderProcessHost>(source).ptr(); |
140 child_process_id = rph->GetID(); | 146 OnChildExit(rph->GetID(), rph->GetHandle()); |
141 pid = rph->GetHandle(); | |
142 break; | |
143 } | |
144 case content::NOTIFICATION_CHILD_PROCESS_CRASHED: | |
145 case content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED: { | |
146 content::ChildProcessData* child_process_data = | |
147 content::Details<content::ChildProcessData>(details).ptr(); | |
148 child_process_id = child_process_data->id; | |
149 pid = child_process_data->handle; | |
150 break; | 147 break; |
151 } | 148 } |
152 default: | 149 default: |
153 NOTREACHED(); | 150 NOTREACHED(); |
154 return; | 151 return; |
155 } | 152 } |
| 153 } |
| 154 |
| 155 void CrashDumpManager::OnChildExit(int child_process_id, |
| 156 base::ProcessHandle pid) { |
156 base::FilePath minidump_path; | 157 base::FilePath minidump_path; |
157 { | 158 { |
158 base::AutoLock auto_lock(child_process_id_to_minidump_path_lock_); | 159 base::AutoLock auto_lock(child_process_id_to_minidump_path_lock_); |
159 ChildProcessIDToMinidumpPath::iterator iter = | 160 ChildProcessIDToMinidumpPath::iterator iter = |
160 child_process_id_to_minidump_path_.find(child_process_id); | 161 child_process_id_to_minidump_path_.find(child_process_id); |
161 if (iter == child_process_id_to_minidump_path_.end()) { | 162 if (iter == child_process_id_to_minidump_path_.end()) { |
162 // We might get a NOTIFICATION_RENDERER_PROCESS_TERMINATED and a | 163 // We might get a NOTIFICATION_RENDERER_PROCESS_TERMINATED and a |
163 // NOTIFICATION_RENDERER_PROCESS_CLOSED. | 164 // NOTIFICATION_RENDERER_PROCESS_CLOSED. |
164 return; | 165 return; |
165 } | 166 } |
166 minidump_path = iter->second; | 167 minidump_path = iter->second; |
167 child_process_id_to_minidump_path_.erase(iter); | 168 child_process_id_to_minidump_path_.erase(iter); |
168 } | 169 } |
169 BrowserThread::PostTask( | 170 BrowserThread::PostTask( |
170 BrowserThread::FILE, FROM_HERE, | 171 BrowserThread::FILE, FROM_HERE, |
171 base::Bind(&CrashDumpManager::ProcessMinidump, minidump_path, pid)); | 172 base::Bind(&CrashDumpManager::ProcessMinidump, minidump_path, pid)); |
172 } | 173 } |
OLD | NEW |