通过源码搞定ANR Log如何产生(六)

1,315 阅读3分钟

通过上文,查看socket name = "kTombstonedJavaTraceSocketName" 的socket服务端

路径为:system/core/debuggerd/tombstoned/tombstoned.cpp

6.1

     main(),java_trace_socket就是在5.12中,链接过来的socket客户端的连接标志,通过这个连接标志,创建一个listener,回调函数为crash_accept_cb()

int main(int, char* []) {
  if (kJavaTraceDumpsEnabled) {
      //从tombstoned_client.cpp的tombstoned_connect所在的客户端连接过来的
    const int java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName);

    evutil_make_socket_nonblocking(java_trace_socket);
    //当触发这个listener监听的时候,回调会在crash_accept_cb中实现
    evconnlistener* java_trace_listener =
        evconnlistener_new(base, crash_accept_cb, CrashQueue::for_anrs(), LEV_OPT_CLOSE_ON_FREE,
                           -1 /* backlog */, java_trace_socket);
   }
}

6.2

    crash_accept_cb(),在这个回调函数中,创建了一个Crash对象,然后调用了回调函数crash_request_cb,将创建的Crash对象传入

    参数:sockfd = android_get_control_socket(kTombstonedJavaTraceSocketName)

static void crash_accept_cb(evconnlistener* listener, evutil_socket_t sockfd, sockaddr*, int,
                            void*) {
  event_base* base = evconnlistener_get_base(listener);
  Crash* crash = new Crash();
  //继续调用了回调crash_request_cb
  event* crash_event = event_new(base, sockfd, EV_TIMEOUT | EV_READ, crash_request_cb, crash);
  //crash->crash_socket_fd = java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName) 从tombstoned_client.cpp的tombstoned_connect所在的客户端连接过来的
  crash->crash_socket_fd.reset(sockfd);
  crash->crash_event = crash_event;
  event_add(crash_event, &timeout);
} 

6.3

     crash_request_cb(),这个函数中,会接收到tombstoned_client.cpp客户端通过write发送的数据,接收载体为request = {packet.packet_type = CrashPacketType::kDumpRequest, packet.packet.dump_request.pid = pid, packet.packet.dump_request.dump_type = dump_type}

     然后将传过来的request中的值,赋值给Crash对象,然后调用perform_request()方法

     参数:sockfd = android_get_control_socket(kTombstonedJavaTraceSocketName) ,arg = new Crash()

//sockfd = java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName) 从tombstoned_client.cpp的tombstoned_connect所在的客户端连接过来的
//arg = crash = new Crash();
static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
  ssize_t rc;
  //获取crash_accept_cb中的new Crash()
  Crash* crash = static_cast(arg);

  TombstonedCrashPacket request = {};
  //read从sockfd中读取客户端发送的数据到request
  //request = {packet.packet_type = CrashPacketType::kDumpRequest,  packet.packet.dump_request.pid = pid, packet.packet.dump_request.dump_type = dump_type}
  rc = TEMP_FAILURE_RETRY(read(sockfd, &request, sizeof(request)));

  //给crash_type赋值 这里crash_type = kDebuggerdJavaBacktrace,所以执行if,给crash_pid赋值为pid
  crash->crash_type = request.packet.dump_request.dump_type;

  if (crash->crash_type != kDebuggerdJavaBacktrace) {
    crash->crash_pid = request.packet.dump_request.pid;
  }
  //maybe_enqueue_crash方法意思是num_concurrent_dumps_ == max_concurrent_dumps_时,将这个crash存入请求队列queued_requests_,排队处理,然后return true。否则执行else
  if (CrashQueue::for_crash(crash)->maybe_enqueue_crash(crash)) {
    LOG(INFO) << "enqueueing crash request for pid " << crash->crash_pid;
  } else {
    perform_request(crash);
  }
  return;
}

6.4

     perform_request(),在这个方法中,会通过调用GetIntercept()方法,传入output_fd,获取4.4中,被赋值的intercept->output_fd = rcv_fd = pipe_write.get(),然后通过SendFileDescriptors()方法,将response和output_fd一起发送给5.12中的socket客户端

//crash->crash_type = kDebuggerdJavaBacktrace
//crash->crash_pid = pid
static void perform_request(Crash* crash) {
  unique_fd output_fd;
  //执行完GetIntercept()后,返回的intercepted在正常情况下为true,所以不执行if内的逻辑
  //pid = crash->crash_pid
  //dump_type = crash->crash_type = kDebuggerdJavaBacktrace
  //output_fd = intercept->output_fd = std::move(rcv_fd) = pipe_write.get()
  bool intercepted = intercept_manager->GetIntercept(crash->crash_pid, crash->crash_type, &output_fd);

  TombstonedCrashPacket response = {
    .packet_type = CrashPacketType::kPerformDump
  };
  //由于crash->crash_socket_fd = java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName) 从tombstoned_client.cpp的tombstoned_connect所在的客户端连接过来的
  //所以SendFileDescriptors,发送response = {.packet_type = CrashPacketType::kPerformDump}   output_fd =  pipe_write.get();
  //到tombstoned_client.cpp的tombstoned_connect中的ReceiveFileDescriptors收取,
  ssize_t rc =
      SendFileDescriptors(crash->crash_socket_fd, &response, sizeof(response), output_fd.get());
  output_fd.reset();
}

--------------------------------------------------------------------------------------------------------------------
//pid = crash->crash_pid
//dump_type = crash->crash_type = kDebuggerdJavaBacktrace
//out_fd = output_fd(是新申明的一个空指针)
bool InterceptManager::GetIntercept(pid_t pid, DebuggerdDumpType dump_type, android::base::unique_fd* out_fd) {
     //判断pid是否相同
  auto it = this->intercepts.find(pid);
  if (it == this->intercepts.end()) {
    return false;
  }
  //判断dump的type是否相同
  if (dump_type == kDebuggerdAnyIntercept) {
    LOG(INFO) << "found registered intercept of type " << it->second->dump_type
              << " for requested type kDebuggerdAnyIntercept";
  } else if (it->second->dump_type != dump_type) {
    LOG(WARNING) << "found non-matching intercept of type " << it->second->dump_type
                 << " for requested type: " << dump_type;
    return false;
  }

  auto intercept = std::move(it->second);
  this->intercepts.erase(it);

  InterceptResponse response = {};
  response.status = InterceptStatus::kStarted;
  //将&response写入intercept->sockfd代表的文件中,即将response写入给 intercept_socket = android_get_control_socket(kTombstonedInterceptSocketName)  代表的socket客户端中
  TEMP_FAILURE_RETRY(write(intercept->sockfd, &response, sizeof(response)));
  //将out_fd指向的地址变为intercept->output_fd指向的地址,intercept->output_fd是在intercept_request_cb中赋值的 
  //intercept->output_fd = std::move(rcv_fd) = pipe_write.get()
  *out_fd = std::move(intercept->output_fd);

  return true;
}

6.5   system/core/debuggerd/client/debuggerd_client.cpp

     debuggerd_trigger_dump()
     1,接收6.4中,通过write()发出的response,判断Started状态
     2,while循环中,读取从5.11中写入管道pipe的数据,然后写入到 ”/data/anr/anr_Date“ 文件中
bool debuggerd_trigger_dump(pid_t tid, DebuggerdDumpType dump_type, unsigned int timeout_ms,
                            unique_fd output_fd) {
  //接收 6.4 中,发出的response
  rc = TEMP_FAILURE_RETRY(recv(set_timeout(sockfd.get()), &response, sizeof(response), MSG_TRUNC));
  if (response.status != InterceptStatus::kStarted) {
    response.error_message[sizeof(response.error_message) - 1] = '\0';
    LOG(ERROR) << "libdebuggerd_client: tombstoned reported failure: " << response.error_message;
    return false;
  }

  // Forward output from the pipe to the output fd.
  while (true) {
      //创建pollfd类型的结构体pfd
    struct pollfd pfd = {
        .fd = pipe_read.get(), .events = POLLIN, .revents = 0,
    };
    //通过poll,将pfd加入监视当中
    rc = poll(&pfd, 1, remaining_ms);

    char buf[1024];
    //通过read方法,读取管道pipe_read.get()中的数据到buf数据
    rc = TEMP_FAILURE_RETRY(read(pipe_read.get(), buf, sizeof(buf)));
    //将buf数组中的内容,写入到文件描述符output_fd指向的文件,从434中可知output_fd =  "/data/anr/anr_Date"的文件描述符
    //所以这个地方是将数据写入到了/data/anr/anr_Date文件中。
    if (!android::base::WriteFully(output_fd.get(), buf, rc)) {
      PLOG(ERROR) << "libdebuggerd_client: error while writing";
      return false;
    }
  }
  //至此,anr的log已经打印完毕
  LOG(INFO) << "libdebuggerd_client: done dumping process " << pid;
  return true;
}