| 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..8c9216ff132e10670f085842169d304b4e621192 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,60 @@ 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),
|
| +#if defined(ADDRESS_SANITIZER)
|
| + std::move(asan_report),
|
| +#endif
|
| + 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,
|
| +#if defined(ADDRESS_SANITIZER)
|
| + std::unique_ptr<char[]> asan_report,
|
| +#endif
|
| + 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 = base::FindThreadIDWithSyscall(
|
| + crashing_pid, 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),
|
| +#if defined(ADDRESS_SANITIZER)
|
| + base::Passed(&asan_report),
|
| +#endif
|
| + 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 +394,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,
|
|
|