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

Side by Side Diff: components/breakpad/browser/crash_handler_host_linux.cc

Issue 296553002: Breakpad Linux: Prevent some memory leaks. (Try 2) (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: fix asan Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « components/breakpad/browser/crash_handler_host_linux.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "components/breakpad/browser/crash_handler_host_linux.h" 5 #include "components/breakpad/browser/crash_handler_host_linux.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <sys/socket.h> 9 #include <sys/socket.h>
10 #include <sys/syscall.h> 10 #include <sys/syscall.h>
11 #include <unistd.h> 11 #include <unistd.h>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
15 #include "base/file_util.h" 15 #include "base/file_util.h"
16 #include "base/files/file_path.h" 16 #include "base/files/file_path.h"
17 #include "base/format_macros.h" 17 #include "base/format_macros.h"
18 #include "base/linux_util.h" 18 #include "base/linux_util.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/memory/singleton.h"
21 #include "base/message_loop/message_loop.h" 20 #include "base/message_loop/message_loop.h"
22 #include "base/path_service.h" 21 #include "base/path_service.h"
23 #include "base/posix/eintr_wrapper.h" 22 #include "base/posix/eintr_wrapper.h"
24 #include "base/rand_util.h" 23 #include "base/rand_util.h"
25 #include "base/strings/string_util.h" 24 #include "base/strings/string_util.h"
26 #include "base/strings/stringprintf.h" 25 #include "base/strings/stringprintf.h"
27 #include "base/threading/thread.h" 26 #include "base/threading/thread.h"
28 #include "breakpad/src/client/linux/handler/exception_handler.h" 27 #include "breakpad/src/client/linux/handler/exception_handler.h"
29 #include "breakpad/src/client/linux/minidump_writer/linux_dumper.h" 28 #include "breakpad/src/client/linux/minidump_writer/linux_dumper.h"
30 #include "breakpad/src/client/linux/minidump_writer/minidump_writer.h" 29 #include "breakpad/src/client/linux/minidump_writer/minidump_writer.h"
31 #include "components/breakpad/app/breakpad_linux_impl.h" 30 #include "components/breakpad/app/breakpad_linux_impl.h"
32 #include "content/public/browser/browser_thread.h" 31 #include "content/public/browser/browser_thread.h"
33 32
34 #if defined(OS_ANDROID) 33 #if defined(OS_ANDROID)
35 #include <sys/linux-syscalls.h> 34 #include <sys/linux-syscalls.h>
36 35
37 #define SYS_read __NR_read 36 #define SYS_read __NR_read
38 #endif 37 #endif
39 38
40 using content::BrowserThread; 39 using content::BrowserThread;
41 using google_breakpad::ExceptionHandler; 40 using google_breakpad::ExceptionHandler;
42 41
43 namespace breakpad { 42 namespace breakpad {
44 43
45 namespace { 44 namespace {
46 45
46 const size_t kNumFDs = 1;
47 // The length of the control message: 47 // The length of the control message:
48 const unsigned kControlMsgSize = 48 const size_t kControlMsgSize =
49 CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); 49 CMSG_SPACE(kNumFDs * sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
50 // The length of the regular payload: 50 // The length of the regular payload:
51 const unsigned kCrashContextSize = sizeof(ExceptionHandler::CrashContext); 51 const size_t kCrashContextSize = sizeof(ExceptionHandler::CrashContext);
52 52
53 // Handles the crash dump and frees the allocated BreakpadInfo struct. 53 // Handles the crash dump and frees the allocated BreakpadInfo struct.
54 void CrashDumpTask(CrashHandlerHostLinux* handler, BreakpadInfo* info) { 54 void CrashDumpTask(CrashHandlerHostLinux* handler,
55 scoped_ptr<BreakpadInfo> info) {
55 if (handler->IsShuttingDown() && info->upload) { 56 if (handler->IsShuttingDown() && info->upload) {
56 base::DeleteFile(base::FilePath(info->filename), false); 57 base::DeleteFile(base::FilePath(info->filename), false);
57 #if defined(ADDRESS_SANITIZER) 58 #if defined(ADDRESS_SANITIZER)
58 base::DeleteFile(base::FilePath(info->log_filename), false); 59 base::DeleteFile(base::FilePath(info->log_filename), false);
59 #endif 60 #endif
60 return; 61 return;
61 } 62 }
62 63
63 HandleCrashDump(*info); 64 HandleCrashDump(*info);
64 delete[] info->filename; 65 delete[] info->filename;
65 #if defined(ADDRESS_SANITIZER) 66 #if defined(ADDRESS_SANITIZER)
66 delete[] info->log_filename; 67 delete[] info->log_filename;
68 delete[] info->asan_report_str;
67 #endif 69 #endif
68 delete[] info->process_type; 70 delete[] info->process_type;
69 delete[] info->distro; 71 delete[] info->distro;
70 delete info->crash_keys; 72 delete info->crash_keys;
71 delete info;
72 } 73 }
73 74
74 } // namespace 75 } // namespace
75 76
76 // Since instances of CrashHandlerHostLinux are leaked, they are only destroyed 77 // Since instances of CrashHandlerHostLinux are leaked, they are only destroyed
77 // at the end of the processes lifetime, which is greater in span than the 78 // at the end of the processes lifetime, which is greater in span than the
78 // lifetime of the IO message loop. Thus, all calls to base::Bind() use 79 // lifetime of the IO message loop. Thus, all calls to base::Bind() use
79 // non-refcounted pointers. 80 // non-refcounted pointers.
80 81
81 CrashHandlerHostLinux::CrashHandlerHostLinux(const std::string& process_type, 82 CrashHandlerHostLinux::CrashHandlerHostLinux(const std::string& process_type,
82 const base::FilePath& dumps_path, 83 const base::FilePath& dumps_path,
83 bool upload) 84 bool upload)
84 : process_type_(process_type), 85 : process_type_(process_type),
85 dumps_path_(dumps_path), 86 dumps_path_(dumps_path),
86 upload_(upload), 87 upload_(upload),
87 shutting_down_(false), 88 shutting_down_(false),
88 worker_pool_token_(BrowserThread::GetBlockingPool()->GetSequenceToken()) { 89 worker_pool_token_(BrowserThread::GetBlockingPool()->GetSequenceToken()) {
89 int fds[2]; 90 int fds[2];
90 // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the process from 91 // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the process from
91 // sending datagrams to other sockets on the system. The sandbox may prevent 92 // sending datagrams to other sockets on the system. The sandbox may prevent
92 // the process from calling socket() to create new sockets, but it'll still 93 // the process from calling socket() to create new sockets, but it'll still
93 // inherit some sockets. With PF_UNIX+SOCK_DGRAM, it can call sendmsg to send 94 // inherit some sockets. With PF_UNIX+SOCK_DGRAM, it can call sendmsg to send
94 // a datagram to any (abstract) socket on the same system. With 95 // a datagram to any (abstract) socket on the same system. With
95 // SOCK_SEQPACKET, this is prevented. 96 // SOCK_SEQPACKET, this is prevented.
96 CHECK_EQ(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds), 0); 97 CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
97 static const int on = 1; 98 static const int on = 1;
98 99
99 // Enable passcred on the server end of the socket 100 // Enable passcred on the server end of the socket
100 CHECK_EQ(setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)), 0); 101 CHECK_EQ(0, setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)));
101 102
102 process_socket_ = fds[0]; 103 process_socket_ = fds[0];
103 browser_socket_ = fds[1]; 104 browser_socket_ = fds[1];
104 105
105 BrowserThread::PostTask( 106 BrowserThread::PostTask(
106 BrowserThread::IO, FROM_HERE, 107 BrowserThread::IO, FROM_HERE,
107 base::Bind(&CrashHandlerHostLinux::Init, base::Unretained(this))); 108 base::Bind(&CrashHandlerHostLinux::Init, base::Unretained(this)));
108 } 109 }
109 110
110 CrashHandlerHostLinux::~CrashHandlerHostLinux() { 111 CrashHandlerHostLinux::~CrashHandlerHostLinux() {
(...skipping 14 matching lines...) Expand all
125 base::MessageLoopForIO::WATCH_READ, 126 base::MessageLoopForIO::WATCH_READ,
126 &file_descriptor_watcher_, this)); 127 &file_descriptor_watcher_, this));
127 ml->AddDestructionObserver(this); 128 ml->AddDestructionObserver(this);
128 } 129 }
129 130
130 void CrashHandlerHostLinux::OnFileCanWriteWithoutBlocking(int fd) { 131 void CrashHandlerHostLinux::OnFileCanWriteWithoutBlocking(int fd) {
131 NOTREACHED(); 132 NOTREACHED();
132 } 133 }
133 134
134 void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { 135 void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) {
135 DCHECK_EQ(fd, browser_socket_); 136 DCHECK_EQ(browser_socket_, fd);
136 137
137 // A process has crashed and has signaled us by writing a datagram 138 // A process has crashed and has signaled us by writing a datagram
138 // to the death signal socket. The datagram contains the crash context needed 139 // to the death signal socket. The datagram contains the crash context needed
139 // for writing the minidump as well as a file descriptor and a credentials 140 // for writing the minidump as well as a file descriptor and a credentials
140 // block so that they can't lie about their pid. 141 // block so that they can't lie about their pid.
141 // 142 //
142 // The message sender is in components/breakpad/app/breakpad_linux.cc. 143 // The message sender is in components/breakpad/app/breakpad_linux.cc.
143 144
144 struct msghdr msg = {0}; 145 struct msghdr msg = {0};
145 struct iovec iov[kCrashIovSize]; 146 struct iovec iov[kCrashIovSize];
146 147
147 // Freed in WriteDumpFile(); 148 scoped_ptr<char[]> crash_context(new char[kCrashContextSize]);
148 char* crash_context = new char[kCrashContextSize];
149 // Freed in CrashDumpTask();
150 char* distro = new char[kDistroSize + 1];
151 #if defined(ADDRESS_SANITIZER) 149 #if defined(ADDRESS_SANITIZER)
152 asan_report_str_ = new char[kMaxAsanReportSize + 1]; 150 scoped_ptr<char[]> asan_report(new char[kMaxAsanReportSize + 1]);
153 #endif 151 #endif
154 152
155 // Freed in CrashDumpTask(). 153 scoped_ptr<CrashKeyStorage> crash_keys(new CrashKeyStorage);
156 CrashKeyStorage* crash_keys = new CrashKeyStorage;
157 google_breakpad::SerializedNonAllocatingMap* serialized_crash_keys; 154 google_breakpad::SerializedNonAllocatingMap* serialized_crash_keys;
158 size_t crash_keys_size = crash_keys->Serialize( 155 size_t crash_keys_size = crash_keys->Serialize(
159 const_cast<const google_breakpad::SerializedNonAllocatingMap**>( 156 const_cast<const google_breakpad::SerializedNonAllocatingMap**>(
160 &serialized_crash_keys)); 157 &serialized_crash_keys));
161 158
162 char* tid_buf_addr = NULL; 159 char* tid_buf_addr = NULL;
163 int tid_fd = -1; 160 int tid_fd = -1;
164 uint64_t uptime; 161 uint64_t uptime;
165 size_t oom_size; 162 size_t oom_size;
166 char control[kControlMsgSize]; 163 char control[kControlMsgSize];
167 const ssize_t expected_msg_size = 164 const ssize_t expected_msg_size =
168 kCrashContextSize + 165 kCrashContextSize +
169 kDistroSize + 1 +
170 sizeof(tid_buf_addr) + sizeof(tid_fd) + 166 sizeof(tid_buf_addr) + sizeof(tid_fd) +
171 sizeof(uptime) + 167 sizeof(uptime) +
172 #if defined(ADDRESS_SANITIZER) 168 #if defined(ADDRESS_SANITIZER)
173 kMaxAsanReportSize + 1 + 169 kMaxAsanReportSize + 1 +
174 #endif 170 #endif
175 sizeof(oom_size) + 171 sizeof(oom_size) +
176 crash_keys_size; 172 crash_keys_size;
177 iov[0].iov_base = crash_context; 173 iov[0].iov_base = crash_context.get();
178 iov[0].iov_len = kCrashContextSize; 174 iov[0].iov_len = kCrashContextSize;
179 iov[1].iov_base = distro; 175 iov[1].iov_base = &tid_buf_addr;
180 iov[1].iov_len = kDistroSize + 1; 176 iov[1].iov_len = sizeof(tid_buf_addr);
181 iov[2].iov_base = &tid_buf_addr; 177 iov[2].iov_base = &tid_fd;
182 iov[2].iov_len = sizeof(tid_buf_addr); 178 iov[2].iov_len = sizeof(tid_fd);
183 iov[3].iov_base = &tid_fd; 179 iov[3].iov_base = &uptime;
184 iov[3].iov_len = sizeof(tid_fd); 180 iov[3].iov_len = sizeof(uptime);
185 iov[4].iov_base = &uptime; 181 iov[4].iov_base = &oom_size;
186 iov[4].iov_len = sizeof(uptime); 182 iov[4].iov_len = sizeof(oom_size);
187 iov[5].iov_base = &oom_size; 183 iov[5].iov_base = serialized_crash_keys;
188 iov[5].iov_len = sizeof(oom_size); 184 iov[5].iov_len = crash_keys_size;
189 iov[6].iov_base = serialized_crash_keys; 185 #if !defined(ADDRESS_SANITIZER)
190 iov[6].iov_len = crash_keys_size; 186 COMPILE_ASSERT(5 == kCrashIovSize - 1, Incorrect_Number_Of_Iovec_Members);
191 #if defined(ADDRESS_SANITIZER) 187 #else
192 iov[7].iov_base = asan_report_str_; 188 iov[6].iov_base = asan_report.get();
193 iov[7].iov_len = kMaxAsanReportSize + 1; 189 iov[6].iov_len = kMaxAsanReportSize + 1;
190 COMPILE_ASSERT(6 == kCrashIovSize - 1, Incorrect_Number_Of_Iovec_Members);
194 #endif 191 #endif
195 msg.msg_iov = iov; 192 msg.msg_iov = iov;
196 msg.msg_iovlen = kCrashIovSize; 193 msg.msg_iovlen = kCrashIovSize;
197 msg.msg_control = control; 194 msg.msg_control = control;
198 msg.msg_controllen = kControlMsgSize; 195 msg.msg_controllen = kControlMsgSize;
199 196
200 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0)); 197 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0));
201 if (msg_size != expected_msg_size) { 198 if (msg_size != expected_msg_size) {
202 LOG(ERROR) << "Error reading from death signal socket. Crash dumping" 199 LOG(ERROR) << "Error reading from death signal socket. Crash dumping"
203 << " is disabled." 200 << " is disabled."
(...skipping 14 matching lines...) Expand all
218 } 215 }
219 216
220 // Walk the control payload an extract the file descriptor and validated pid. 217 // Walk the control payload an extract the file descriptor and validated pid.
221 pid_t crashing_pid = -1; 218 pid_t crashing_pid = -1;
222 int signal_fd = -1; 219 int signal_fd = -1;
223 for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; 220 for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr;
224 hdr = CMSG_NXTHDR(&msg, hdr)) { 221 hdr = CMSG_NXTHDR(&msg, hdr)) {
225 if (hdr->cmsg_level != SOL_SOCKET) 222 if (hdr->cmsg_level != SOL_SOCKET)
226 continue; 223 continue;
227 if (hdr->cmsg_type == SCM_RIGHTS) { 224 if (hdr->cmsg_type == SCM_RIGHTS) {
228 const unsigned len = hdr->cmsg_len - 225 const size_t len = hdr->cmsg_len -
229 (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr); 226 (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
230 DCHECK_EQ(len % sizeof(int), 0u); 227 DCHECK_EQ(0U, len % sizeof(int));
231 const unsigned num_fds = len / sizeof(int); 228 const size_t num_fds = len / sizeof(int);
232 if (num_fds != 1) { 229 if (num_fds != kNumFDs) {
233 // A nasty process could try and send us too many descriptors and 230 // A nasty process could try and send us too many descriptors and
234 // force a leak. 231 // force a leak.
235 LOG(ERROR) << "Death signal contained wrong number of descriptors;" 232 LOG(ERROR) << "Death signal contained wrong number of descriptors;"
236 << " num_fds:" << num_fds; 233 << " num_fds:" << num_fds;
237 for (unsigned i = 0; i < num_fds; ++i) 234 for (size_t i = 0; i < num_fds; ++i)
238 close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]); 235 close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]);
239 return; 236 return;
240 } else { 237 } else {
241 signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0]; 238 signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0];
242 } 239 }
243 } else if (hdr->cmsg_type == SCM_CREDENTIALS) { 240 } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
244 const struct ucred *cred = 241 const struct ucred *cred =
245 reinterpret_cast<struct ucred*>(CMSG_DATA(hdr)); 242 reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
246 crashing_pid = cred->pid; 243 crashing_pid = cred->pid;
247 } 244 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 // guess here and assume the crashing thread is the thread group 280 // guess here and assume the crashing thread is the thread group
284 // leader. If procfs syscall is not supported by the kernel, then 281 // leader. If procfs syscall is not supported by the kernel, then
285 // we assume the kernel also does not support TID namespacing and 282 // we assume the kernel also does not support TID namespacing and
286 // trust the TID passed by the crashing process. 283 // trust the TID passed by the crashing process.
287 LOG(WARNING) << "Could not translate tid - assuming crashing thread is " 284 LOG(WARNING) << "Could not translate tid - assuming crashing thread is "
288 "thread group leader; syscall_supported=" << syscall_supported; 285 "thread group leader; syscall_supported=" << syscall_supported;
289 crashing_tid = crashing_pid; 286 crashing_tid = crashing_pid;
290 } 287 }
291 288
292 ExceptionHandler::CrashContext* bad_context = 289 ExceptionHandler::CrashContext* bad_context =
293 reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context); 290 reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context.get());
294 bad_context->tid = crashing_tid; 291 bad_context->tid = crashing_tid;
295 292
296 // Freed in CrashDumpTask(); 293 scoped_ptr<BreakpadInfo> info(new BreakpadInfo);
297 BreakpadInfo* info = new BreakpadInfo;
298 294
299 info->fd = -1; 295 info->fd = -1;
300 info->process_type_length = process_type_.length(); 296 info->process_type_length = process_type_.length();
297 // Freed in CrashDumpTask().
301 char* process_type_str = new char[info->process_type_length + 1]; 298 char* process_type_str = new char[info->process_type_length + 1];
302 process_type_.copy(process_type_str, info->process_type_length); 299 process_type_.copy(process_type_str, info->process_type_length);
303 process_type_str[info->process_type_length] = '\0'; 300 process_type_str[info->process_type_length] = '\0';
304 info->process_type = process_type_str; 301 info->process_type = process_type_str;
305 302
306 info->distro_length = strlen(distro); 303 std::string distro = base::GetLinuxDistro();
jochen (gone - plz use gerrit) 2014/05/22 10:52:28 this method crashes in thread restrictions :-/
307 info->distro = distro; 304 info->distro_length = distro.length();
305 // Freed in CrashDumpTask().
306 char* distro_str = new char[info->distro_length + 1];
307 distro.copy(distro_str, info->distro_length);
308 distro_str[info->distro_length] = '\0';
309 info->distro = distro_str;
310
311 // Memory released from scoped_ptrs below are also freed in CrashDumpTask().
312 info->crash_keys = crash_keys.release();
313 #if defined(ADDRESS_SANITIZER)
314 asan_report[kMaxAsanReportSize] = '\0';
315 info->asan_report_str = asan_report.release();
316 info->asan_report_length = strlen(info->asan_report_str);
317 #endif
318
319 info->process_start_time = uptime;
320 info->oom_size = oom_size;
308 #if defined(OS_ANDROID) 321 #if defined(OS_ANDROID)
309 // Nothing gets uploaded in android. 322 // Nothing gets uploaded in android.
310 info->upload = false; 323 info->upload = false;
311 #else 324 #else
312 info->upload = upload_; 325 info->upload = upload_;
313 #endif 326 #endif
314 327
315 info->crash_keys = crash_keys;
316
317 #if defined(ADDRESS_SANITIZER)
318 info->asan_report_str = asan_report_str_;
319 info->asan_report_length = strlen(asan_report_str_);
320 #endif
321 info->process_start_time = uptime;
322 info->oom_size = oom_size;
323 328
324 BrowserThread::GetBlockingPool()->PostSequencedWorkerTask( 329 BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
325 worker_pool_token_, 330 worker_pool_token_,
326 FROM_HERE, 331 FROM_HERE,
327 base::Bind(&CrashHandlerHostLinux::WriteDumpFile, 332 base::Bind(&CrashHandlerHostLinux::WriteDumpFile,
328 base::Unretained(this), 333 base::Unretained(this),
329 info, 334 base::Passed(&info),
335 base::Passed(&crash_context),
330 crashing_pid, 336 crashing_pid,
331 crash_context,
332 signal_fd)); 337 signal_fd));
333 } 338 }
334 339
335 void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info, 340 void CrashHandlerHostLinux::WriteDumpFile(scoped_ptr<BreakpadInfo> info,
341 scoped_ptr<char[]> crash_context,
336 pid_t crashing_pid, 342 pid_t crashing_pid,
337 char* crash_context,
338 int signal_fd) { 343 int signal_fd) {
339 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( 344 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
340 worker_pool_token_)); 345 worker_pool_token_));
341 346
342 base::FilePath dumps_path("/tmp"); 347 base::FilePath dumps_path("/tmp");
343 PathService::Get(base::DIR_TEMP, &dumps_path); 348 PathService::Get(base::DIR_TEMP, &dumps_path);
344 if (!info->upload) 349 if (!info->upload)
345 dumps_path = dumps_path_; 350 dumps_path = dumps_path_;
346 const uint64 rand = base::RandUint64();
347 const std::string minidump_filename = 351 const std::string minidump_filename =
348 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp", 352 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp",
349 dumps_path.value().c_str(), 353 dumps_path.value().c_str(),
350 process_type_.c_str(), 354 process_type_.c_str(),
351 rand); 355 base::RandUint64());
352 356
353 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), 357 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(),
354 kMaxMinidumpFileSize, 358 kMaxMinidumpFileSize,
355 crashing_pid, crash_context, 359 crashing_pid,
360 crash_context.get(),
356 kCrashContextSize, 361 kCrashContextSize,
357 google_breakpad::MappingList(), 362 google_breakpad::MappingList(),
358 google_breakpad::AppMemoryList())) { 363 google_breakpad::AppMemoryList())) {
359 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid; 364 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid;
360 } 365 }
361 #if defined(ADDRESS_SANITIZER) 366 #if defined(ADDRESS_SANITIZER)
362 // Create a temporary file holding the AddressSanitizer report. 367 // Create a temporary file holding the AddressSanitizer report.
363 const std::string log_filename = 368 const base::FilePath log_path =
364 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".log", 369 base::FilePath(minidump_filename).ReplaceExtension("log");
365 dumps_path.value().c_str(), 370 base::WriteFile(log_path, info->asan_report_str, info->asan_report_length);
366 process_type_.c_str(),
367 rand);
368 FILE* logfile = fopen(log_filename.c_str(), "w");
369 CHECK(logfile);
370 fprintf(logfile, "%s", asan_report_str_);
371 fclose(logfile);
372 #endif 371 #endif
373 372
374 delete[] crash_context; 373 // Freed in CrashDumpTask().
375
376 // Freed in CrashDumpTask();
377 char* minidump_filename_str = new char[minidump_filename.length() + 1]; 374 char* minidump_filename_str = new char[minidump_filename.length() + 1];
378 minidump_filename.copy(minidump_filename_str, minidump_filename.length()); 375 minidump_filename.copy(minidump_filename_str, minidump_filename.length());
379 minidump_filename_str[minidump_filename.length()] = '\0'; 376 minidump_filename_str[minidump_filename.length()] = '\0';
380 info->filename = minidump_filename_str; 377 info->filename = minidump_filename_str;
381 #if defined(ADDRESS_SANITIZER) 378 #if defined(ADDRESS_SANITIZER)
379 // Freed in CrashDumpTask().
382 char* minidump_log_filename_str = new char[minidump_filename.length() + 1]; 380 char* minidump_log_filename_str = new char[minidump_filename.length() + 1];
383 minidump_filename.copy(minidump_log_filename_str, minidump_filename.length()); 381 minidump_filename.copy(minidump_log_filename_str, minidump_filename.length());
384 memcpy(minidump_log_filename_str + minidump_filename.length() - 3, "log", 3); 382 memcpy(minidump_log_filename_str + minidump_filename.length() - 3, "log", 3);
385 minidump_log_filename_str[minidump_filename.length()] = '\0'; 383 minidump_log_filename_str[minidump_filename.length()] = '\0';
386 info->log_filename = minidump_log_filename_str; 384 info->log_filename = minidump_log_filename_str;
387 #endif 385 #endif
388 info->pid = crashing_pid; 386 info->pid = crashing_pid;
389 387
390 BrowserThread::PostTask( 388 BrowserThread::PostTask(
391 BrowserThread::IO, FROM_HERE, 389 BrowserThread::IO, FROM_HERE,
392 base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask, 390 base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask,
393 base::Unretained(this), 391 base::Unretained(this),
394 info, 392 base::Passed(&info),
395 signal_fd)); 393 signal_fd));
396 } 394 }
397 395
398 void CrashHandlerHostLinux::QueueCrashDumpTask(BreakpadInfo* info, 396 void CrashHandlerHostLinux::QueueCrashDumpTask(scoped_ptr<BreakpadInfo> info,
399 int signal_fd) { 397 int signal_fd) {
400 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
401 399
402 // Send the done signal to the process: it can exit now. 400 // Send the done signal to the process: it can exit now.
403 struct msghdr msg = {0}; 401 struct msghdr msg = {0};
404 struct iovec done_iov; 402 struct iovec done_iov;
405 done_iov.iov_base = const_cast<char*>("\x42"); 403 done_iov.iov_base = const_cast<char*>("\x42");
406 done_iov.iov_len = 1; 404 done_iov.iov_len = 1;
407 msg.msg_iov = &done_iov; 405 msg.msg_iov = &done_iov;
408 msg.msg_iovlen = 1; 406 msg.msg_iovlen = 1;
409 407
410 (void) HANDLE_EINTR(sendmsg(signal_fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL)); 408 HANDLE_EINTR(sendmsg(signal_fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL));
411 close(signal_fd); 409 close(signal_fd);
412 410
413 uploader_thread_->message_loop()->PostTask( 411 uploader_thread_->message_loop()->PostTask(
414 FROM_HERE, 412 FROM_HERE,
415 base::Bind(&CrashDumpTask, base::Unretained(this), info)); 413 base::Bind(&CrashDumpTask, base::Unretained(this), base::Passed(&info)));
416 } 414 }
417 415
418 void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() { 416 void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() {
419 file_descriptor_watcher_.StopWatchingFileDescriptor(); 417 file_descriptor_watcher_.StopWatchingFileDescriptor();
420 418
421 // If we are quitting and there are crash dumps in the queue, turn them into 419 // If we are quitting and there are crash dumps in the queue, turn them into
422 // no-ops. 420 // no-ops.
423 shutting_down_ = true; 421 shutting_down_ = true;
424 uploader_thread_->Stop(); 422 uploader_thread_->Stop();
425 } 423 }
426 424
427 bool CrashHandlerHostLinux::IsShuttingDown() const { 425 bool CrashHandlerHostLinux::IsShuttingDown() const {
428 return shutting_down_; 426 return shutting_down_;
429 } 427 }
430 428
431 } // namespace breakpad 429 } // namespace breakpad
OLDNEW
« no previous file with comments | « components/breakpad/browser/crash_handler_host_linux.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698