| 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"); |
| 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 |