6.1
main()、java_trace_socketは5.12で、ソケットクライアントの接続フラグにリンクされ、この接続フラグを介して、リスナー、crash_accept_cb()のコールバック関数を作成します。
int main(int, char* []) {
if (kJavaTraceDumpsEnabled) {
//tombstonedより_client.cpp墓石がある_connectに接続する。
const int java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName);
evutil_make_socket_nonblocking(java_trace_socket);
//このリスナーがトリガーされると、コールバックがクラッシュでトリガーされる_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();
//コールバック・クラッシュが続く_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墓石がある_connectに接続する。
crash->crash_socket_fd.reset(sockfd);
crash->crash_event = crash_event;
event_add(crash_event, &timeout);
}
6.3
そして、渡されたリクエストの値をCrashオブジェクトに代入し、perform_request()メソッドを呼び出します。
パラメータ: sockfd = android_get_control_socket(kTombstonedJavaTraceSocketName) , arg = new Crash()
//sockfd = java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName) tombstonedより_client.cpp墓石がある_connectに接続する。
//arg = crash = new Crash();
static void crash_request_cb(evutil_socket_t sockfd, short ev, void* arg) {
ssize_t rc;
//クラッシュを取得する_accept_cbファイル"/data/anr/anr_Date "の newCrash()
Crash* crash = static_cast(arg);
TombstonedCrashPacket request = {};
//readクライアントがsockfdからリクエストに送ったデータを読む
//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)));
//クラッシュを与える_typeここに値を割り当てる。_type = kDebuggerdJavaBacktrace,そこで、ifを実行し、クラッシュを与える_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_とき、このクラッシュをキューイングされたリクエスト・キューに格納する。_requests_,処理をキューに入れ、trueを返す。
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
//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_socket_fd = java_trace_socket = android_get_control_socket(kTombstonedJavaTraceSocketName) tombstonedより_client.cpp墓石がある_connectに接続する。
//SendFileDescriptorsで、レスポンスを送信する。 = {.packet_type = CrashPacketType::kPerformDump} output_fd = pipe_write.get()
//に書き込む。_client.cpp墓石がある_connectファイル"/data/anr/anr_Date "内のReceiveFileDescriptorsは、"/data/anr/anr_Date "ファイル内のデータをチャージする。,
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;
}
//ダンプの種類が同じかどうかを判断する
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インターセプトに書き込む>sockfdファイルに書き込み、その応答をインターセプトに書き込む。_socket = android_get_control_socket(kTombstonedInterceptSocketName) ファイル"/data/anr/anr_Date "で表されるソケットクライアントに書き込む。
TEMP_FAILURE_RETRY(write(intercept->sockfd, &response, sizeof(response)));
//を書き出す。_fd指されたアドレスはintercept-となる。>output_fdポインタのアドレス,intercept->output_fdがインターセプトにある。_request_cbに書き込む。
//intercept->output_fd = std::move(rcv_fd) = pipe_write.get()
*out_fd = std::move(intercept->output_fd);
return true;
}
6.5
debuggerd_trigger_dump()
1、6.4でwrite()が発行したレスポンスを受け取り、Startedステータスを判断。
2、whileループで、5.11でパイプ管に書き込まれたデータを読み込み、ファイル"/data/anr/anr_Date "に書き込みます。
bool debuggerd_trigger_dump(pid_t tid, DebuggerdDumpType dump_type, unsigned int timeout_ms,
unique_fd output_fd) {
//6を受け取る。.4 発行されたレスポンスでは
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;
//readメソッドでパイプを読む。_read.get()ファイル"/data/anr/anr_Date "の buf data に書き込む。
rc = TEMP_FAILURE_RETRY(read(pipe_read.get(), buf, sizeof(buf)));
//buf 配列の内容をファイルディスクリプタ出力に書き込む。_fd434から指し示されるファイルは、出力として知られている。_fd = "/data/anr/anr_Date"のファイル・ディスクリプタは"/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(INFO) << "libdebuggerd_client: done dumping process " << pid;
return true;
}



