Chromium Code Reviews| Index: components/crash/content/browser/crash_handler_host_linux.cc |
| diff --git a/components/crash/content/browser/crash_handler_host_linux.cc b/components/crash/content/browser/crash_handler_host_linux.cc |
| index 393c047450e04e13dd57502f640e152e922269fb..779374b8c3f520f352596b1cbf4dbf4e32e5a9fe 100644 |
| --- a/components/crash/content/browser/crash_handler_host_linux.cc |
| +++ b/components/crash/content/browser/crash_handler_host_linux.cc |
| @@ -28,6 +28,7 @@ |
| #include "base/strings/string_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/threading/thread.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| #include "breakpad/src/client/linux/handler/exception_handler.h" |
| #include "breakpad/src/client/linux/minidump_writer/linux_dumper.h" |
| #include "breakpad/src/client/linux/minidump_writer/minidump_writer.h" |
| @@ -55,6 +56,12 @@ const size_t kControlMsgSize = |
| // The length of the regular payload: |
| const size_t kCrashContextSize = sizeof(ExceptionHandler::CrashContext); |
| +// Crashing thread might be in "running" state, i.e. after sys_sendmsg() and |
| +// before sys_read(). Retry 3 times with interval of 100 ms when translating |
| +// TID. |
| +const int kNumAttemptsTranslatingTid = 3; |
| +const int kRetryIntervalTranslatingTidInMs = 100; |
| + |
| // Handles the crash dump and frees the allocated BreakpadInfo struct. |
| void CrashDumpTask(CrashHandlerHostLinux* handler, |
| std::unique_ptr<BreakpadInfo> info) { |
| @@ -280,11 +287,53 @@ void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { |
| // but we just check syscall_number through arg3. |
| base::StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ", |
| SYS_read, tid_fd, tid_buf_addr); |
| + |
| + FindCrashingThreadAndDump(crashing_pid, |
| + expected_syscall_data, |
| + std::move(crash_context), |
| + std::move(crash_keys), |
| + uptime, |
| + oom_size, |
| + signal_fd.release(), |
| + 0); |
| +} |
| + |
| +void CrashHandlerHostLinux::FindCrashingThreadAndDump( |
| + pid_t crashing_pid, |
| + const std::string& expected_syscall_data, |
| + std::unique_ptr<char[]> crash_context, |
| + std::unique_ptr<CrashKeyStorage> crash_keys, |
| + uint64_t uptime, |
| + size_t oom_size, |
| + int signal_fd, |
| + int attempt) { |
| bool syscall_supported = false; |
| - pid_t crashing_tid = |
| - base::FindThreadIDWithSyscall(crashing_pid, |
| - expected_syscall_data, |
| - &syscall_supported); |
| + pid_t crashing_tid = -1; |
| + crashing_tid = base::FindThreadIDWithSyscall(crashing_pid, |
|
Lei Zhang
2016/07/25 18:46:57
Combine with previous line?
wzhong
2016/07/25 19:27:46
Done.
|
| + expected_syscall_data, |
| + &syscall_supported); |
| + ++attempt; |
| + if (crashing_tid == -1 && syscall_supported && |
| + attempt <= kNumAttemptsTranslatingTid) { |
| + LOG(WARNING) << "Could not translate tid, attempt = " << attempt |
| + << " retry ..."; |
| + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&CrashHandlerHostLinux::FindCrashingThreadAndDump, |
| + base::Unretained(this), |
| + crashing_pid, |
| + expected_syscall_data, |
| + base::Passed(&crash_context), |
| + base::Passed(&crash_keys), |
| + uptime, |
| + oom_size, |
| + signal_fd, |
| + attempt), |
| + base::TimeDelta::FromMilliseconds(kRetryIntervalTranslatingTidInMs)); |
| + return; |
| + } |
| + |
| + |
| if (crashing_tid == -1) { |
| // We didn't find the thread we want. Maybe it didn't reach |
| // sys_read() yet or the thread went away. We'll just take a |
| @@ -338,7 +387,7 @@ void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) { |
| base::Passed(&info), |
| base::Passed(&crash_context), |
| crashing_pid, |
| - signal_fd.release())); |
| + signal_fd)); |
| } |
| void CrashHandlerHostLinux::WriteDumpFile(std::unique_ptr<BreakpadInfo> info, |