18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/crash/browser/crash_handler_host_linux.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/syscall.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/files/scoped_file.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/linux_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/linux/handler/exception_handler.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/linux/minidump_writer/linux_dumper.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "breakpad/src/client/linux/minidump_writer/minidump_writer.h"
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/crash/app/breakpad_linux_impl.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_ANDROID) && !defined(__LP64__)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/linux-syscalls.h>
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SYS_read __NR_read
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using google_breakpad::ExceptionHandler;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace breakpad {
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kNumFDs = 1;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The length of the control message:
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kControlMsgSize =
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CMSG_SPACE(kNumFDs * sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The length of the regular payload:
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kCrashContextSize = sizeof(ExceptionHandler::CrashContext);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handles the crash dump and frees the allocated BreakpadInfo struct.
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CrashDumpTask(CrashHandlerHostLinux* handler,
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   scoped_ptr<BreakpadInfo> info) {
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (handler->IsShuttingDown() && info->upload) {
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DeleteFile(base::FilePath(info->filename), false);
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(ADDRESS_SANITIZER)
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DeleteFile(base::FilePath(info->log_filename), false);
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HandleCrashDump(*info);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete[] info->filename;
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(ADDRESS_SANITIZER)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  delete[] info->log_filename;
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  delete[] info->asan_report_str;
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete[] info->process_type;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete[] info->distro;
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  delete info->crash_keys;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Since instances of CrashHandlerHostLinux are leaked, they are only destroyed
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// at the end of the processes lifetime, which is greater in span than the
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// lifetime of the IO message loop. Thus, all calls to base::Bind() use
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-refcounted pointers.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)CrashHandlerHostLinux::CrashHandlerHostLinux(const std::string& process_type,
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                             const base::FilePath& dumps_path,
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                             bool upload)
868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : process_type_(process_type),
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      dumps_path_(dumps_path),
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      upload_(upload),
898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      shutting_down_(false),
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      worker_pool_token_(BrowserThread::GetBlockingPool()->GetSequenceToken()) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fds[2];
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use SOCK_SEQPACKET rather than SOCK_DGRAM to prevent the process from
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sending datagrams to other sockets on the system. The sandbox may prevent
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the process from calling socket() to create new sockets, but it'll still
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inherit some sockets. With PF_UNIX+SOCK_DGRAM, it can call sendmsg to send
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a datagram to any (abstract) socket on the same system. With
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SOCK_SEQPACKET, this is prevented.
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int on = 1;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enable passcred on the server end of the socket
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_EQ(0, setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_socket_ = fds[0];
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  browser_socket_ = fds[1];
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CrashHandlerHostLinux::Init, base::Unretained(this)));
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CrashHandlerHostLinux::~CrashHandlerHostLinux() {
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  close(process_socket_);
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  close(browser_socket_);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void CrashHandlerHostLinux::StartUploaderThread() {
1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  uploader_thread_.reset(
1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      new base::Thread(process_type_ + "_crash_uploader"));
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  uploader_thread_->Start();
1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashHandlerHostLinux::Init() {
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO* ml = base::MessageLoopForIO::current();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(ml->WatchFileDescriptor(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_socket_, true /* persistent */,
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoopForIO::WATCH_READ,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &file_descriptor_watcher_, this));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ml->AddDestructionObserver(this);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashHandlerHostLinux::OnFileCanWriteWithoutBlocking(int fd) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashHandlerHostLinux::OnFileCanReadWithoutBlocking(int fd) {
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(browser_socket_, fd);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A process has crashed and has signaled us by writing a datagram
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the death signal socket. The datagram contains the crash context needed
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for writing the minidump as well as a file descriptor and a credentials
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // block so that they can't lie about their pid.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The message sender is in components/crash/app/breakpad_linux.cc.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct msghdr msg = {0};
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  struct iovec iov[kCrashIovSize];
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<char[]> crash_context(new char[kCrashContextSize]);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ADDRESS_SANITIZER)
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<char[]> asan_report(new char[kMaxAsanReportSize + 1]);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<CrashKeyStorage> crash_keys(new CrashKeyStorage);
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  google_breakpad::SerializedNonAllocatingMap* serialized_crash_keys;
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  size_t crash_keys_size = crash_keys->Serialize(
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const_cast<const google_breakpad::SerializedNonAllocatingMap**>(
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          &serialized_crash_keys));
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* tid_buf_addr = NULL;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tid_fd = -1;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64_t uptime;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t oom_size;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char control[kControlMsgSize];
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ssize_t expected_msg_size =
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kCrashContextSize +
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sizeof(tid_buf_addr) + sizeof(tid_fd) +
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sizeof(uptime) +
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ADDRESS_SANITIZER)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kMaxAsanReportSize + 1 +
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sizeof(oom_size) +
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      crash_keys_size;
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[0].iov_base = crash_context.get();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  iov[0].iov_len = kCrashContextSize;
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[1].iov_base = &tid_buf_addr;
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[1].iov_len = sizeof(tid_buf_addr);
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[2].iov_base = &tid_fd;
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[2].iov_len = sizeof(tid_fd);
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[3].iov_base = &uptime;
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[3].iov_len = sizeof(uptime);
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[4].iov_base = &oom_size;
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[4].iov_len = sizeof(oom_size);
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[5].iov_base = serialized_crash_keys;
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[5].iov_len = crash_keys_size;
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if !defined(ADDRESS_SANITIZER)
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  COMPILE_ASSERT(5 == kCrashIovSize - 1, Incorrect_Number_Of_Iovec_Members);
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[6].iov_base = asan_report.get();
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  iov[6].iov_len = kMaxAsanReportSize + 1;
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  COMPILE_ASSERT(6 == kCrashIovSize - 1, Incorrect_Number_Of_Iovec_Members);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg.msg_iov = iov;
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  msg.msg_iovlen = kCrashIovSize;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg.msg_control = control;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg.msg_controllen = kControlMsgSize;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ssize_t msg_size = HANDLE_EINTR(recvmsg(browser_socket_, &msg, 0));
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (msg_size < 0) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Error reading from death signal socket. Crash dumping"
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " is disabled."
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " msg_size:" << msg_size
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " errno:" << errno;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_descriptor_watcher_.StopWatchingFileDescriptor();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const bool bad_message = (msg_size != expected_msg_size ||
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            msg.msg_controllen != kControlMsgSize ||
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            msg.msg_flags & ~MSG_TRUNC);
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::ScopedFD signal_fd;
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  pid_t crashing_pid = -1;
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (msg.msg_controllen > 0) {
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Walk the control payload and extract the file descriptor and
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // validated pid.
21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr;
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         hdr = CMSG_NXTHDR(&msg, hdr)) {
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (hdr->cmsg_level != SOL_SOCKET)
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        continue;
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (hdr->cmsg_type == SCM_RIGHTS) {
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        const size_t len = hdr->cmsg_len -
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        DCHECK_EQ(0U, len % sizeof(int));
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        const size_t num_fds = len / sizeof(int);
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (num_fds != kNumFDs) {
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          // A nasty process could try and send us too many descriptors and
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          // force a leak.
22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          LOG(ERROR) << "Death signal contained wrong number of descriptors;"
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     << " num_fds:" << num_fds;
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          for (size_t i = 0; i < num_fds; ++i)
23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]);
23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          return;
23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        }
23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        DCHECK(!signal_fd.is_valid());
23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        int fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0];
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        DCHECK_GE(fd, 0);  // The kernel should never send a negative fd.
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        signal_fd.reset(fd);
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        DCHECK_EQ(-1, crashing_pid);
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        const struct ucred *cred =
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        crashing_pid = cred->pid;
24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (bad_message) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Received death signal message with the wrong size;"
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " msg.msg_controllen:" << msg.msg_controllen
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " msg.msg_flags:" << msg.msg_flags
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " kCrashContextSize:" << kCrashContextSize
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " kControlMsgSize:" << kControlMsgSize;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (crashing_pid == -1 || !signal_fd.is_valid()) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Death signal message didn't contain all expected control"
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " messages";
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The crashing TID set inside the compromised context via
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sys_gettid() in ExceptionHandler::HandleSignal might be wrong (if
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the kernel supports PID namespacing) and may need to be
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // translated.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We expect the crashing thread to be in sys_read(), waiting for us to
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // write to |signal_fd|. Most newer kernels where we have the different pid
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // namespaces also have /proc/[pid]/syscall, so we can look through
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |actual_crashing_pid|'s thread group and find the thread that's in the
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // read syscall with the right arguments.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string expected_syscall_data;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // /proc/[pid]/syscall is formatted as follows:
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // syscall_number arg1 ... arg6 sp pc
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // but we just check syscall_number through arg3.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(&expected_syscall_data, "%d 0x%x %p 0x1 ",
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      SYS_read, tid_fd, tid_buf_addr);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool syscall_supported = false;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pid_t crashing_tid =
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::FindThreadIDWithSyscall(crashing_pid,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    expected_syscall_data,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &syscall_supported);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (crashing_tid == -1) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We didn't find the thread we want. Maybe it didn't reach
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sys_read() yet or the thread went away.  We'll just take a
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // guess here and assume the crashing thread is the thread group
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // leader.  If procfs syscall is not supported by the kernel, then
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we assume the kernel also does not support TID namespacing and
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // trust the TID passed by the crashing process.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Could not translate tid - assuming crashing thread is "
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "thread group leader; syscall_supported=" << syscall_supported;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crashing_tid = crashing_pid;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExceptionHandler::CrashContext* bad_context =
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reinterpret_cast<ExceptionHandler::CrashContext*>(crash_context.get());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bad_context->tid = crashing_tid;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<BreakpadInfo> info(new BreakpadInfo);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->fd = -1;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->process_type_length = process_type_.length();
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Freed in CrashDumpTask().
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* process_type_str = new char[info->process_type_length + 1];
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_type_.copy(process_type_str, info->process_type_length);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_type_str[info->process_type_length] = '\0';
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->process_type = process_type_str;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Memory released from scoped_ptrs below are also freed in CrashDumpTask().
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  info->crash_keys = crash_keys.release();
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(ADDRESS_SANITIZER)
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  asan_report[kMaxAsanReportSize] = '\0';
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  info->asan_report_str = asan_report.release();
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  info->asan_report_length = strlen(info->asan_report_str);
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  info->process_start_time = uptime;
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  info->oom_size = oom_size;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nothing gets uploaded in android.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->upload = false;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  info->upload = upload_;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  BrowserThread::GetBlockingPool()->PostSequencedWorkerTask(
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      worker_pool_token_,
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CrashHandlerHostLinux::WriteDumpFile,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this),
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Passed(&info),
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Passed(&crash_context),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 crashing_pid,
33446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 signal_fd.release()));
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CrashHandlerHostLinux::WriteDumpFile(scoped_ptr<BreakpadInfo> info,
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          scoped_ptr<char[]> crash_context,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          pid_t crashing_pid,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int signal_fd) {
3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      worker_pool_token_));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set |info->distro| here because base::GetLinuxDistro() needs to run on a
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // blocking thread.
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string distro = base::GetLinuxDistro();
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  info->distro_length = distro.length();
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Freed in CrashDumpTask().
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  char* distro_str = new char[info->distro_length + 1];
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  distro.copy(distro_str, info->distro_length);
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  distro_str[info->distro_length] = '\0';
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  info->distro = distro_str;
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath dumps_path("/tmp");
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PathService::Get(base::DIR_TEMP, &dumps_path);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info->upload)
3578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    dumps_path = dumps_path_;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string minidump_filename =
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPrintf("%s/chromium-%s-minidump-%016" PRIx64 ".dmp",
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         dumps_path.value().c_str(),
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         process_type_.c_str(),
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                         base::RandUint64());
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!google_breakpad::WriteMinidump(minidump_filename.c_str(),
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      kMaxMinidumpFileSize,
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      crashing_pid,
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      crash_context.get(),
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      kCrashContextSize,
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      google_breakpad::MappingList(),
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      google_breakpad::AppMemoryList())) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to write crash dump for pid " << crashing_pid;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ADDRESS_SANITIZER)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a temporary file holding the AddressSanitizer report.
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const base::FilePath log_path =
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::FilePath(minidump_filename).ReplaceExtension("log");
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::WriteFile(log_path, info->asan_report_str, info->asan_report_length);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Freed in CrashDumpTask().
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* minidump_filename_str = new char[minidump_filename.length() + 1];
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  minidump_filename.copy(minidump_filename_str, minidump_filename.length());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  minidump_filename_str[minidump_filename.length()] = '\0';
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->filename = minidump_filename_str;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ADDRESS_SANITIZER)
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Freed in CrashDumpTask().
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* minidump_log_filename_str = new char[minidump_filename.length() + 1];
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  minidump_filename.copy(minidump_log_filename_str, minidump_filename.length());
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(minidump_log_filename_str + minidump_filename.length() - 3, "log", 3);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  minidump_log_filename_str[minidump_filename.length()] = '\0';
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->log_filename = minidump_log_filename_str;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->pid = crashing_pid;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CrashHandlerHostLinux::QueueCrashDumpTask,
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this),
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Passed(&info),
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 signal_fd));
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CrashHandlerHostLinux::QueueCrashDumpTask(scoped_ptr<BreakpadInfo> info,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               int signal_fd) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the done signal to the process: it can exit now.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct msghdr msg = {0};
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct iovec done_iov;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done_iov.iov_base = const_cast<char*>("\x42");
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  done_iov.iov_len = 1;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg.msg_iov = &done_iov;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg.msg_iovlen = 1;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  HANDLE_EINTR(sendmsg(signal_fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL));
416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  close(signal_fd);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uploader_thread_->message_loop()->PostTask(
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&CrashDumpTask, base::Unretained(this), base::Passed(&info)));
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CrashHandlerHostLinux::WillDestroyCurrentMessageLoop() {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_descriptor_watcher_.StopWatchingFileDescriptor();
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we are quitting and there are crash dumps in the queue, turn them into
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // no-ops.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shutting_down_ = true;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uploader_thread_->Stop();
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CrashHandlerHostLinux::IsShuttingDown() const {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return shutting_down_;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace breakpad
437