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/crash_handler_host_linux.h" | 5 #include "chrome/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> |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { | 121 void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { |
122 DCHECK_EQ(fd, browser_socket_); | 122 DCHECK_EQ(fd, browser_socket_); |
123 | 123 |
124 // A process has crashed and has signaled us by writing a datagram | 124 // A process has crashed and has signaled us by writing a datagram |
125 // to the death signal socket. The datagram contains the crash context needed | 125 // to the death signal socket. The datagram contains the crash context needed |
126 // for writing the minidump as well as a file descriptor and a credentials | 126 // for writing the minidump as well as a file descriptor and a credentials |
127 // block so that they can't lie about their pid. | 127 // block so that they can't lie about their pid. |
128 // | 128 // |
129 // The message sender is in chrome/app/breakpad_linux.cc. | 129 // The message sender is in chrome/app/breakpad_linux.cc. |
130 | 130 |
131 #if !defined(ADDRESS_SANITIZER) | |
131 const size_t kIovSize = 8; | 132 const size_t kIovSize = 8; |
133 #else | |
134 const size_t kIovSize = 9; | |
135 #endif | |
136 | |
132 struct msghdr msg = {0}; | 137 struct msghdr msg = {0}; |
133 struct iovec iov[kIovSize]; | 138 struct iovec iov[kIovSize]; |
134 | 139 |
135 // Freed in WriteDumpFile(); | 140 // Freed in WriteDumpFile(); |
136 char* crash_context = new char[kCrashContextSize]; | 141 char* crash_context = new char[kCrashContextSize]; |
137 // Freed in CrashDumpTask(); | 142 // Freed in CrashDumpTask(); |
138 char* guid = new char[kGuidSize + 1]; | 143 char* guid = new char[kGuidSize + 1]; |
139 char* crash_url = new char[kMaxActiveURLSize + 1]; | 144 char* crash_url = new char[kMaxActiveURLSize + 1]; |
140 char* distro = new char[kDistroSize + 1]; | 145 char* distro = new char[kDistroSize + 1]; |
146 #if defined(ADDRESS_SANITIZER) | |
147 asan_report_str_ = new char[kMaxAsanReportSize + 1]; | |
148 #endif | |
141 | 149 |
142 char* tid_buf_addr = NULL; | 150 char* tid_buf_addr = NULL; |
143 int tid_fd = -1; | 151 int tid_fd = -1; |
144 uint64_t uptime; | 152 uint64_t uptime; |
145 size_t oom_size; | 153 size_t oom_size; |
146 char control[kControlMsgSize]; | 154 char control[kControlMsgSize]; |
147 const ssize_t expected_msg_size = | 155 const ssize_t expected_msg_size = |
148 kCrashContextSize + | 156 kCrashContextSize + |
149 kGuidSize + 1 + | 157 kGuidSize + 1 + |
150 kMaxActiveURLSize + 1 + | 158 kMaxActiveURLSize + 1 + |
151 kDistroSize + 1 + | 159 kDistroSize + 1 + |
152 sizeof(tid_buf_addr) + sizeof(tid_fd) + | 160 sizeof(tid_buf_addr) + sizeof(tid_fd) + |
153 sizeof(uptime) + | 161 sizeof(uptime) + |
162 #if defined(ADDRESS_SANITIZER) | |
163 kMaxAsanReportSize + 1 + | |
164 #endif | |
154 sizeof(oom_size); | 165 sizeof(oom_size); |
155 | |
156 iov[0].iov_base = crash_context; | 166 iov[0].iov_base = crash_context; |
157 iov[0].iov_len = kCrashContextSize; | 167 iov[0].iov_len = kCrashContextSize; |
158 iov[1].iov_base = guid; | 168 iov[1].iov_base = guid; |
159 iov[1].iov_len = kGuidSize + 1; | 169 iov[1].iov_len = kGuidSize + 1; |
160 iov[2].iov_base = crash_url; | 170 iov[2].iov_base = crash_url; |
161 iov[2].iov_len = kMaxActiveURLSize + 1; | 171 iov[2].iov_len = kMaxActiveURLSize + 1; |
162 iov[3].iov_base = distro; | 172 iov[3].iov_base = distro; |
163 iov[3].iov_len = kDistroSize + 1; | 173 iov[3].iov_len = kDistroSize + 1; |
164 iov[4].iov_base = &tid_buf_addr; | 174 iov[4].iov_base = &tid_buf_addr; |
165 iov[4].iov_len = sizeof(tid_buf_addr); | 175 iov[4].iov_len = sizeof(tid_buf_addr); |
166 iov[5].iov_base = &tid_fd; | 176 iov[5].iov_base = &tid_fd; |
167 iov[5].iov_len = sizeof(tid_fd); | 177 iov[5].iov_len = sizeof(tid_fd); |
168 iov[6].iov_base = &uptime; | 178 iov[6].iov_base = &uptime; |
169 iov[6].iov_len = sizeof(uptime); | 179 iov[6].iov_len = sizeof(uptime); |
170 iov[7].iov_base = &oom_size; | 180 iov[7].iov_base = &oom_size; |
171 iov[7].iov_len = sizeof(oom_size); | 181 iov[7].iov_len = sizeof(oom_size); |
182 #if defined(ADDRESS_SANITIZER) | |
183 iov[8].iov_base = asan_report_str_; | |
184 iov[8].iov_len = kMaxAsanReportSize + 1; | |
185 #endif | |
172 msg.msg_iov = iov; | 186 msg.msg_iov = iov; |
173 msg.msg_iovlen = kIovSize; | 187 msg.msg_iovlen = kIovSize; |
174 msg.msg_control = control; | 188 msg.msg_control = control; |
175 msg.msg_controllen = kControlMsgSize; | 189 msg.msg_controllen = kControlMsgSize; |
176 | 190 |
177 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0)); | 191 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0)); |
178 if (msg_size != expected_msg_size) { | 192 if (msg_size != expected_msg_size) { |
179 LOG(ERROR) << "Error reading from death signal socket. Crash dumping" | 193 LOG(ERROR) << "Error reading from death signal socket. Crash dumping" |
180 << " is disabled." | 194 << " is disabled." |
181 << " msg_size:" << msg_size | 195 << " msg_size:" << msg_size |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 info->guid = guid; | 337 info->guid = guid; |
324 | 338 |
325 info->distro_length = strlen(distro); | 339 info->distro_length = strlen(distro); |
326 info->distro = distro; | 340 info->distro = distro; |
327 #if defined(OS_ANDROID) | 341 #if defined(OS_ANDROID) |
328 // Nothing gets uploaded in android. | 342 // Nothing gets uploaded in android. |
329 info->upload = false; | 343 info->upload = false; |
330 #else | 344 #else |
331 info->upload = (getenv(env_vars::kHeadless) == NULL); | 345 info->upload = (getenv(env_vars::kHeadless) == NULL); |
332 #endif | 346 #endif |
347 | |
348 #if defined(ADDRESS_SANITIZER) | |
349 info->asan_report_str = asan_report_str_; | |
350 info->asan_report_length = strlen(asan_report_str_); | |
351 #endif | |
333 info->process_start_time = uptime; | 352 info->process_start_time = uptime; |
334 info->oom_size = oom_size; | 353 info->oom_size = oom_size; |
335 | 354 |
336 BrowserThread::PostTask( | 355 BrowserThread::PostTask( |
337 BrowserThread::FILE, FROM_HERE, | 356 BrowserThread::FILE, FROM_HERE, |
338 base::Bind(&CrashHandlerHostLinux::WriteDumpFile, | 357 base::Bind(&CrashHandlerHostLinux::WriteDumpFile, |
339 base::Unretained(this), | 358 base::Unretained(this), |
340 info, | 359 info, |
341 crashing_pid, | 360 crashing_pid, |
342 crash_context, | 361 crash_context, |
343 signal_fd)); | 362 signal_fd)); |
344 } | 363 } |
345 | 364 |
346 void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info, | 365 void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info, |
347 pid_t crashing_pid, | 366 pid_t crashing_pid, |
348 char* crash_context, | 367 char* crash_context, |
349 int signal_fd) { | 368 int signal_fd) { |
350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
351 | 370 |
352 FilePath dumps_path("/tmp"); | 371 FilePath dumps_path("/tmp"); |
353 PathService::Get(base::DIR_TEMP, &dumps_path); | 372 PathService::Get(base::DIR_TEMP, &dumps_path); |
354 if (!info->upload) | 373 if (!info->upload) |
355 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); | 374 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); |
356 const uint64 rand = base::RandUint64(); | 375 const uint64 rand = base::RandUint64(); |
357 const std::string minidump_filename = | 376 const std::string minidump_filename = |
358 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp", | 377 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp", |
359 dumps_path.value().c_str(), | 378 dumps_path.value().c_str(), |
360 process_type_.c_str(), | 379 process_type_.c_str(), |
361 rand); | 380 rand); |
381 | |
362 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), | 382 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), |
363 crashing_pid, crash_context, | 383 crashing_pid, crash_context, |
364 kCrashContextSize)) { | 384 kCrashContextSize)) { |
365 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid; | 385 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid; |
366 } | 386 } |
387 #if defined(ADDRESS_SANITIZER) | |
388 // Create a temporary file holding the AddressSanitizer report. | |
389 const std::string log_filename = | |
390 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".log", | |
391 dumps_path.value().c_str(), | |
392 process_type_.c_str(), | |
393 rand); | |
394 FILE *logfile = fopen(log_filename.c_str(), "w"); | |
Lei Zhang
2012/08/21 18:35:17
nit: FILE*
Lei Zhang
2012/08/21 18:35:17
Check and make sure |logfile| is not NULL?
Alexander Potapenko
2012/08/22 12:15:08
Done.
Alexander Potapenko
2012/08/22 12:15:08
Done.
| |
395 fprintf(logfile, "%s", asan_report_str_); | |
396 fclose(logfile); | |
397 #endif | |
398 | |
367 delete[] crash_context; | 399 delete[] crash_context; |
368 | 400 |
369 // Freed in CrashDumpTask(); | 401 // Freed in CrashDumpTask(); |
370 char* minidump_filename_str = new char[minidump_filename.length() + 1]; | 402 char* minidump_filename_str = new char[minidump_filename.length() + 1]; |
371 minidump_filename.copy(minidump_filename_str, minidump_filename.length()); | 403 minidump_filename.copy(minidump_filename_str, minidump_filename.length()); |
372 minidump_filename_str[minidump_filename.length()] = '\0'; | 404 minidump_filename_str[minidump_filename.length()] = '\0'; |
373 info->filename = minidump_filename_str; | 405 info->filename = minidump_filename_str; |
406 #if defined(ADDRESS_SANITIZER) | |
407 char* minidump_log_filename_str = new char[minidump_filename.length() + 1]; | |
408 minidump_filename.copy(minidump_log_filename_str, minidump_filename.length()); | |
409 strcpy(minidump_log_filename_str + minidump_filename.length() - 3, "log"); | |
410 minidump_log_filename_str[minidump_filename.length()] = '\0'; | |
411 info->log_filename = minidump_log_filename_str; | |
412 #endif | |
374 info->pid = crashing_pid; | 413 info->pid = crashing_pid; |
375 | 414 |
376 BrowserThread::PostTask( | 415 BrowserThread::PostTask( |
377 BrowserThread::IO, FROM_HERE, | 416 BrowserThread::IO, FROM_HERE, |
378 base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask, | 417 base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask, |
379 base::Unretained(this), | 418 base::Unretained(this), |
380 info, | 419 info, |
381 signal_fd)); | 420 signal_fd)); |
382 } | 421 } |
383 | 422 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 } | 525 } |
487 | 526 |
488 void RendererCrashHandlerHostLinux::SetProcessType() { | 527 void RendererCrashHandlerHostLinux::SetProcessType() { |
489 process_type_ = "renderer"; | 528 process_type_ = "renderer"; |
490 } | 529 } |
491 | 530 |
492 // static | 531 // static |
493 RendererCrashHandlerHostLinux* RendererCrashHandlerHostLinux::GetInstance() { | 532 RendererCrashHandlerHostLinux* RendererCrashHandlerHostLinux::GetInstance() { |
494 return Singleton<RendererCrashHandlerHostLinux>::get(); | 533 return Singleton<RendererCrashHandlerHostLinux>::get(); |
495 } | 534 } |
OLD | NEW |