blog

ソースコード(VI)からANRログを生成する方法

以上で、ソケットサーバー側のビューのパス=""は...

May 24, 2020 · 7 min. read
シェア

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;
}
Read next

システム・アーキテクチャ設計ノート - デザイン・パターン

オブジェクト指向技術は、ソフトウェア技術に新たな発展をもたらします。人々は、オブジェクト指向のアイデアを使用してシステムを分析し、システムをモデル化し、システムを設計し、最終的にオブジェクト指向プログラミング言語を使用してシステムを実装します。しかし、オブジェクト指向の設計は非常に簡単なものではなく、特に、よく設計されたソフトウェアシステムを設計することは容易ではありません。システムの再利用性を向上させるためには、いくつかの「余分な」設計が必要です(ここでは...

May 24, 2020 · 25 min read