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) | |
132 const size_t kIovSize = 8; | 131 const size_t kIovSize = 8; |
133 #else | |
134 const size_t kIovSize = 9; | |
135 #endif | |
136 | |
137 struct msghdr msg = {0}; | 132 struct msghdr msg = {0}; |
138 struct iovec iov[kIovSize]; | 133 struct iovec iov[kIovSize]; |
139 | 134 |
140 // Freed in WriteDumpFile(); | 135 // Freed in WriteDumpFile(); |
141 char* crash_context = new char[kCrashContextSize]; | 136 char* crash_context = new char[kCrashContextSize]; |
142 // Freed in CrashDumpTask(); | 137 // Freed in CrashDumpTask(); |
143 char* guid = new char[kGuidSize + 1]; | 138 char* guid = new char[kGuidSize + 1]; |
144 char* crash_url = new char[kMaxActiveURLSize + 1]; | 139 char* crash_url = new char[kMaxActiveURLSize + 1]; |
145 char* distro = new char[kDistroSize + 1]; | 140 char* distro = new char[kDistroSize + 1]; |
146 #if defined(ADDRESS_SANITIZER) | |
147 asan_report_str_ = new char[kMaxAsanReportSize + 1]; | |
148 #endif | |
149 | 141 |
150 char* tid_buf_addr = NULL; | 142 char* tid_buf_addr = NULL; |
151 int tid_fd = -1; | 143 int tid_fd = -1; |
152 uint64_t uptime; | 144 uint64_t uptime; |
153 size_t oom_size; | 145 size_t oom_size; |
154 char control[kControlMsgSize]; | 146 char control[kControlMsgSize]; |
155 const ssize_t expected_msg_size = | 147 const ssize_t expected_msg_size = |
156 kCrashContextSize + | 148 kCrashContextSize + |
157 kGuidSize + 1 + | 149 kGuidSize + 1 + |
158 kMaxActiveURLSize + 1 + | 150 kMaxActiveURLSize + 1 + |
159 kDistroSize + 1 + | 151 kDistroSize + 1 + |
160 sizeof(tid_buf_addr) + sizeof(tid_fd) + | 152 sizeof(tid_buf_addr) + sizeof(tid_fd) + |
161 sizeof(uptime) + | 153 sizeof(uptime) + |
162 #if defined(ADDRESS_SANITIZER) | |
163 kMaxAsanReportSize + 1 + | |
164 #endif | |
165 sizeof(oom_size); | 154 sizeof(oom_size); |
| 155 |
166 iov[0].iov_base = crash_context; | 156 iov[0].iov_base = crash_context; |
167 iov[0].iov_len = kCrashContextSize; | 157 iov[0].iov_len = kCrashContextSize; |
168 iov[1].iov_base = guid; | 158 iov[1].iov_base = guid; |
169 iov[1].iov_len = kGuidSize + 1; | 159 iov[1].iov_len = kGuidSize + 1; |
170 iov[2].iov_base = crash_url; | 160 iov[2].iov_base = crash_url; |
171 iov[2].iov_len = kMaxActiveURLSize + 1; | 161 iov[2].iov_len = kMaxActiveURLSize + 1; |
172 iov[3].iov_base = distro; | 162 iov[3].iov_base = distro; |
173 iov[3].iov_len = kDistroSize + 1; | 163 iov[3].iov_len = kDistroSize + 1; |
174 iov[4].iov_base = &tid_buf_addr; | 164 iov[4].iov_base = &tid_buf_addr; |
175 iov[4].iov_len = sizeof(tid_buf_addr); | 165 iov[4].iov_len = sizeof(tid_buf_addr); |
176 iov[5].iov_base = &tid_fd; | 166 iov[5].iov_base = &tid_fd; |
177 iov[5].iov_len = sizeof(tid_fd); | 167 iov[5].iov_len = sizeof(tid_fd); |
178 iov[6].iov_base = &uptime; | 168 iov[6].iov_base = &uptime; |
179 iov[6].iov_len = sizeof(uptime); | 169 iov[6].iov_len = sizeof(uptime); |
180 iov[7].iov_base = &oom_size; | 170 iov[7].iov_base = &oom_size; |
181 iov[7].iov_len = sizeof(oom_size); | 171 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 | |
186 msg.msg_iov = iov; | 172 msg.msg_iov = iov; |
187 msg.msg_iovlen = kIovSize; | 173 msg.msg_iovlen = kIovSize; |
188 msg.msg_control = control; | 174 msg.msg_control = control; |
189 msg.msg_controllen = kControlMsgSize; | 175 msg.msg_controllen = kControlMsgSize; |
190 | 176 |
191 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0)); | 177 const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0)); |
192 if (msg_size != expected_msg_size) { | 178 if (msg_size != expected_msg_size) { |
193 LOG(ERROR) << "Error reading from death signal socket. Crash dumping" | 179 LOG(ERROR) << "Error reading from death signal socket. Crash dumping" |
194 << " is disabled." | 180 << " is disabled." |
195 << " msg_size:" << msg_size | 181 << " msg_size:" << msg_size |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 info->guid = guid; | 323 info->guid = guid; |
338 | 324 |
339 info->distro_length = strlen(distro); | 325 info->distro_length = strlen(distro); |
340 info->distro = distro; | 326 info->distro = distro; |
341 #if defined(OS_ANDROID) | 327 #if defined(OS_ANDROID) |
342 // Nothing gets uploaded in android. | 328 // Nothing gets uploaded in android. |
343 info->upload = false; | 329 info->upload = false; |
344 #else | 330 #else |
345 info->upload = (getenv(env_vars::kHeadless) == NULL); | 331 info->upload = (getenv(env_vars::kHeadless) == NULL); |
346 #endif | 332 #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 | |
352 info->process_start_time = uptime; | 333 info->process_start_time = uptime; |
353 info->oom_size = oom_size; | 334 info->oom_size = oom_size; |
354 | 335 |
355 BrowserThread::PostTask( | 336 BrowserThread::PostTask( |
356 BrowserThread::FILE, FROM_HERE, | 337 BrowserThread::FILE, FROM_HERE, |
357 base::Bind(&CrashHandlerHostLinux::WriteDumpFile, | 338 base::Bind(&CrashHandlerHostLinux::WriteDumpFile, |
358 base::Unretained(this), | 339 base::Unretained(this), |
359 info, | 340 info, |
360 crashing_pid, | 341 crashing_pid, |
361 crash_context, | 342 crash_context, |
362 signal_fd)); | 343 signal_fd)); |
363 } | 344 } |
364 | 345 |
365 void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info, | 346 void CrashHandlerHostLinux::WriteDumpFile(BreakpadInfo* info, |
366 pid_t crashing_pid, | 347 pid_t crashing_pid, |
367 char* crash_context, | 348 char* crash_context, |
368 int signal_fd) { | 349 int signal_fd) { |
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 350 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
370 | 351 |
371 FilePath dumps_path("/tmp"); | 352 FilePath dumps_path("/tmp"); |
372 PathService::Get(base::DIR_TEMP, &dumps_path); | 353 PathService::Get(base::DIR_TEMP, &dumps_path); |
373 if (!info->upload) | 354 if (!info->upload) |
374 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); | 355 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); |
375 const uint64 rand = base::RandUint64(); | 356 const uint64 rand = base::RandUint64(); |
376 const std::string minidump_filename = | 357 const std::string minidump_filename = |
377 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp", | 358 base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp", |
378 dumps_path.value().c_str(), | 359 dumps_path.value().c_str(), |
379 process_type_.c_str(), | 360 process_type_.c_str(), |
380 rand); | 361 rand); |
381 | |
382 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), | 362 if (!google_breakpad::WriteMinidump(minidump_filename.c_str(), |
383 crashing_pid, crash_context, | 363 crashing_pid, crash_context, |
384 kCrashContextSize)) { | 364 kCrashContextSize)) { |
385 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid; | 365 LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid; |
386 } | 366 } |
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 | |
399 delete[] crash_context; | 367 delete[] crash_context; |
400 | 368 |
401 // Freed in CrashDumpTask(); | 369 // Freed in CrashDumpTask(); |
402 char* minidump_filename_str = new char[minidump_filename.length() + 1]; | 370 char* minidump_filename_str = new char[minidump_filename.length() + 1]; |
403 minidump_filename.copy(minidump_filename_str, minidump_filename.length()); | 371 minidump_filename.copy(minidump_filename_str, minidump_filename.length()); |
404 minidump_filename_str[minidump_filename.length()] = '\0'; | 372 minidump_filename_str[minidump_filename.length()] = '\0'; |
405 info->filename = minidump_filename_str; | 373 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 | |
413 info->pid = crashing_pid; | 374 info->pid = crashing_pid; |
414 | 375 |
415 BrowserThread::PostTask( | 376 BrowserThread::PostTask( |
416 BrowserThread::IO, FROM_HERE, | 377 BrowserThread::IO, FROM_HERE, |
417 base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask, | 378 base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask, |
418 base::Unretained(this), | 379 base::Unretained(this), |
419 info, | 380 info, |
420 signal_fd)); | 381 signal_fd)); |
421 } | 382 } |
422 | 383 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 } | 486 } |
526 | 487 |
527 void RendererCrashHandlerHostLinux::SetProcessType() { | 488 void RendererCrashHandlerHostLinux::SetProcessType() { |
528 process_type_ = "renderer"; | 489 process_type_ = "renderer"; |
529 } | 490 } |
530 | 491 |
531 // static | 492 // static |
532 RendererCrashHandlerHostLinux* RendererCrashHandlerHostLinux::GetInstance() { | 493 RendererCrashHandlerHostLinux* RendererCrashHandlerHostLinux::GetInstance() { |
533 return Singleton<RendererCrashHandlerHostLinux>::get(); | 494 return Singleton<RendererCrashHandlerHostLinux>::get(); |
534 } | 495 } |
OLD | NEW |