| 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 |