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

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: Use base::SyncSocket 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 <unistd.h>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/stl_util.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/child_process_data.h"
14 #include "content/public/browser/notification_service.h"
15 #include "content/public/browser/notification_types.h"
16 #include "content/public/browser/render_process_host.h"
17
18 using content::BrowserThread;
19
20 namespace breakpad {
21
22 // static
23 CrashMicroDumpManager* CrashMicroDumpManager::instance_ = nullptr;
24
25 // static
26 CrashMicroDumpManager* CrashMicroDumpManager::GetInstance() {
Robert Sesek 2016/01/07 20:02:22 This object is both constructible and has singleto
mnaganov (inactive) 2016/01/07 21:39:50 AwBrowserContext isn't global enough -- we used to
27 CHECK(instance_);
28 return instance_;
29 }
30
31 CrashMicroDumpManager::CrashMicroDumpManager() : weak_factory_(this) {
32 DCHECK_CURRENTLY_ON(BrowserThread::UI);
33 DCHECK(!instance_);
34
35 instance_ = this;
36
37 notification_registrar_.Add(this,
38 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
39 content::NotificationService::AllSources());
40 notification_registrar_.Add(this,
41 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
42 content::NotificationService::AllSources());
43 }
44
45 CrashMicroDumpManager::~CrashMicroDumpManager() {
46 instance_ = nullptr;
47 {
48 base::AutoLock auto_lock(child_process_id_to_pipe_lock_);
49 STLDeleteValues(&child_process_id_to_pipe_);
Robert Sesek 2016/01/07 20:02:22 If you switch to scoped_ptr<> in the map, you'll s
mnaganov (inactive) 2016/01/07 21:39:50 Done.
50 }
51 }
52
53 base::ScopedFD CrashMicroDumpManager::CreateCrashInfoChannel(
54 int child_process_id) {
55 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
56 scoped_ptr<base::SyncSocket> local_pipe(new base::SyncSocket());
57 scoped_ptr<base::SyncSocket> child_pipe(new base::SyncSocket());
58 if (!base::SyncSocket::CreatePair(local_pipe.get(), child_pipe.get()))
59 return base::ScopedFD();
60 {
61 base::AutoLock auto_lock(child_process_id_to_pipe_lock_);
62 DCHECK(!ContainsKey(child_process_id_to_pipe_, child_process_id));
63 child_process_id_to_pipe_[child_process_id] = local_pipe.release();
64 }
65 return std::move(base::ScopedFD(dup(child_pipe->handle())));
66 }
67
68 void CrashMicroDumpManager::HandleChildTerminationOnFileThread(
69 int child_process_id,
70 base::TerminationStatus termination_status) {
71 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
72
73 scoped_ptr<base::SyncSocket> pipe;
74 {
75 base::AutoLock auto_lock(child_process_id_to_pipe_lock_);
76 const auto& iter = child_process_id_to_pipe_.find(child_process_id);
77 if (iter == child_process_id_to_pipe_.end()) {
78 // We might get a NOTIFICATION_RENDERER_PROCESS_TERMINATED and a
79 // NOTIFICATION_RENDERER_PROCESS_CLOSED.
80 return;
81 }
82 pipe.reset(iter->second);
83 child_process_id_to_pipe_.erase(iter);
84 }
85 DCHECK(pipe->handle() != base::SyncSocket::kInvalidHandle);
86
87 if (termination_status == base::TERMINATION_STATUS_NORMAL_TERMINATION)
88 return;
89 if (pipe->Peek() >= sizeof(int)) {
90 int exit_code;
91 pipe->Receive(&exit_code, sizeof(exit_code));
92 LOG(FATAL) << "Renderer process crash detected (code " << exit_code
93 << "). Terminating browser.";
94 } else {
95 // The child process hasn't written anything into the pipe. This implies
96 // that it was terminated via SIGKILL by the low memory killer, and thus we
97 // need to perform a clean exit.
98 exit(0);
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 termination_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 termination_status = process_details->status;
126 }
127 break;
128 }
129 default:
130 NOTREACHED();
131 return;
132 }
133 BrowserThread::PostTask(
134 BrowserThread::FILE, FROM_HERE,
135 base::Bind(&CrashMicroDumpManager::HandleChildTerminationOnFileThread,
136 weak_factory_.GetWeakPtr(), rph->GetID(),
137 termination_status));
138 }
139
140 } // namespace breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698