From 1ffd8fa8ad21ebdc0b06aae0d5cc238cfe361320 Mon Sep 17 00:00:00 2001 From: cs1111 Date: Sat, 9 Aug 2025 15:39:30 +0800 Subject: [PATCH] fix:Code optimization Signed-off-by: cs1111 Change-Id: I8c9884bd4df0a4d1630af4628e9270f501a6f75b --- .../localhandler/dfx_signal_local_handler.cpp | 4 +- .../src/utils/dfx_frame_formatter.cpp | 2 +- test/unittest/coredump/BUILD.gn | 1 + test/unittest/process_dump/BUILD.gn | 2 + .../process_dump/dfx_processdump_test.cpp | 2 +- .../process_dump/thread_dump_info_test.cpp | 6 - tools/dump_catcher/BUILD.gn | 1 + tools/process_dump/BUILD.gn | 5 +- tools/process_dump/decorative_dump_info.h | 9 +- tools/process_dump/dfx_process.h | 13 +- tools/process_dump/dfx_thread.cpp | 9 +- tools/process_dump/dfx_thread.h | 2 +- tools/process_dump/dump_info.h | 1 - .../process_dump/dump_info_json_formatter.cpp | 2 +- tools/process_dump/key_thread_dump_info.cpp | 18 +- tools/process_dump/key_thread_dump_info.h | 1 - tools/process_dump/other_thread_dump_info.cpp | 16 +- tools/process_dump/process_dumper.cpp | 297 ++++++++---------- tools/process_dump/process_dumper.h | 23 +- tools/process_dump/reporter.cpp | 20 +- tools/process_dump/{ => utils}/dump_utils.cpp | 78 ++++- tools/process_dump/{ => utils}/dump_utils.h | 5 + tools/process_dump/utils/thread_pool.cpp | 113 +++++++ tools/process_dump/utils/thread_pool.h | 49 +++ 24 files changed, 450 insertions(+), 229 deletions(-) rename tools/process_dump/{ => utils}/dump_utils.cpp (70%) rename tools/process_dump/{ => utils}/dump_utils.h (78%) create mode 100644 tools/process_dump/utils/thread_pool.cpp create mode 100644 tools/process_dump/utils/thread_pool.h diff --git a/frameworks/localhandler/dfx_signal_local_handler.cpp b/frameworks/localhandler/dfx_signal_local_handler.cpp index cff33f089..a19313738 100644 --- a/frameworks/localhandler/dfx_signal_local_handler.cpp +++ b/frameworks/localhandler/dfx_signal_local_handler.cpp @@ -82,7 +82,7 @@ static int DoCrashHandler(void* arg) { int sig = *(static_cast(arg)); RegisterAllocator(); - DFXLOGI("DoCrashHandler::start handle sig(%d)", sig); + DFXLOGI("DoCrashHandler::start handle sig(%{public}d)", sig); if (sig == SIGALRM) { if (g_sigAlarmCallbackFn != nullptr) { g_sigAlarmCallbackFn(); @@ -98,7 +98,7 @@ static int DoCrashHandler(void* arg) } } } - DFXLOGI("DoCrashHandler::finish handle sig(%d)", sig); + DFXLOGI("DoCrashHandler::finish handle sig(%{public}d)", sig); UnregisterAllocator(); pthread_mutex_unlock(&g_signalHandlerMutex); _exit(0); diff --git a/interfaces/innerkits/unwinder/src/utils/dfx_frame_formatter.cpp b/interfaces/innerkits/unwinder/src/utils/dfx_frame_formatter.cpp index 1fdc4ee99..95e418d2d 100644 --- a/interfaces/innerkits/unwinder/src/utils/dfx_frame_formatter.cpp +++ b/interfaces/innerkits/unwinder/src/utils/dfx_frame_formatter.cpp @@ -62,7 +62,7 @@ std::string DfxFrameFormatter::GetFrameStr(const DfxFrame& frame) } else { data += " [Unknown]"; } - if (frame.parseSymbolState.IsParseSymbolComplete() && !frame.funcName.empty() && + if (!frame.funcName.empty() && frame.funcName.length() <= MAX_FUNC_NAME_LEN) { data += "(" + frame.funcName; data += StringPrintf("+%" PRId64, frame.funcOffset); diff --git a/test/unittest/coredump/BUILD.gn b/test/unittest/coredump/BUILD.gn index e666177dd..af3006509 100644 --- a/test/unittest/coredump/BUILD.gn +++ b/test/unittest/coredump/BUILD.gn @@ -35,6 +35,7 @@ if (defined(ohos_lite)) { "$faultloggerd_path/test/utils", "$faultloggerd_path/tools/process_dump", "$faultloggerd_path/tools/process_dump/coredump", + "$faultloggerd_path/tools/process_dump/utils", ] } diff --git a/test/unittest/process_dump/BUILD.gn b/test/unittest/process_dump/BUILD.gn index 1a18b815f..a679de1f7 100644 --- a/test/unittest/process_dump/BUILD.gn +++ b/test/unittest/process_dump/BUILD.gn @@ -32,6 +32,7 @@ if (defined(ohos_lite)) { "$faultloggerd_path/test/utils", "$faultloggerd_path/tools/process_dump", "$faultloggerd_path/tools/process_dump/coredump", + "$faultloggerd_path/tools/process_dump/utils", "$hilog_lite_include_path", ] @@ -72,6 +73,7 @@ if (defined(ohos_lite)) { "$faultloggerd_path/test/utils", "$faultloggerd_path/tools/process_dump", "$faultloggerd_path/tools/process_dump/coredump", + "$faultloggerd_path/tools/process_dump/utils", "$faultloggerd_path/tools/process_dump/lperf", ] } diff --git a/test/unittest/process_dump/dfx_processdump_test.cpp b/test/unittest/process_dump/dfx_processdump_test.cpp index 874b42b3e..531ae2758 100644 --- a/test/unittest/process_dump/dfx_processdump_test.cpp +++ b/test/unittest/process_dump/dfx_processdump_test.cpp @@ -418,7 +418,7 @@ HWTEST_F(DfxProcessDumpTest, DfxProcessDumpTest018, TestSize.Level2) ASSERT_FALSE(ins.InitBufferWriter()); ins.request_.type = ProcessDumpType::DUMP_TYPE_DUMP_CATCH; - ins.WriteDumpResIfNeed(1); + ins.WriteDumpResIfNeed(DumpErrorCode::DUMP_ESUCCESS); GTEST_LOG_(INFO) << "DfxProcessDumpTest018: end."; } diff --git a/test/unittest/process_dump/thread_dump_info_test.cpp b/test/unittest/process_dump/thread_dump_info_test.cpp index 3aba65807..6be483ce6 100644 --- a/test/unittest/process_dump/thread_dump_info_test.cpp +++ b/test/unittest/process_dump/thread_dump_info_test.cpp @@ -111,7 +111,6 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest001, TestSize.Level2) unwinder.EnableFillFrames(false); KeyThreadDumpInfo dumpInfo; EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); - dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { "Tid:", @@ -168,7 +167,6 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest002, TestSize.Level2) unwinder.EnableFillFrames(false); KeyThreadDumpInfo dumpInfo; EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); - dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { "Tid:", @@ -216,7 +214,6 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest003, TestSize.Level2) unwinder.EnableFillFrames(false); KeyThreadDumpInfo dumpInfo; EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); - dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { "Fault thread info:", @@ -258,7 +255,6 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest004, TestSize.Level2) unwinder.EnableFillFrames(false); OtherThreadDumpInfo dumpInfo; EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); - dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { "Other thread info:", @@ -301,7 +297,6 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest005, TestSize.Level2) unwinder.EnableFillFrames(false); OtherThreadDumpInfo dumpInfo; EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); - dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { "Tid:", @@ -346,7 +341,6 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest006, TestSize.Level2) OtherThreadDumpInfo dumpInfo; dumpInfo.SetDumpInfo(keyThreadDumpInfo); EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), threadCount); - dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { "Tid:", diff --git a/tools/dump_catcher/BUILD.gn b/tools/dump_catcher/BUILD.gn index 7da132d41..845bf60db 100644 --- a/tools/dump_catcher/BUILD.gn +++ b/tools/dump_catcher/BUILD.gn @@ -49,6 +49,7 @@ if (defined(ohos_lite)) { "$faultloggerd_interfaces_path/common", "$faultloggerd_path/interfaces/innerkits/signal_handler", "$faultloggerd_path/tools/process_dump", + "$faultloggerd_path/tools/process_dump/utils", ] } diff --git a/tools/process_dump/BUILD.gn b/tools/process_dump/BUILD.gn index 6bc8880f9..bcfce7876 100644 --- a/tools/process_dump/BUILD.gn +++ b/tools/process_dump/BUILD.gn @@ -19,7 +19,6 @@ processdump_sources = [ "dfx_thread.cpp", "dump_info_header.cpp", "dump_info_json_formatter.cpp", - "dump_utils.cpp", "extra_crash_info.cpp", "fault_stack.cpp", "key_thread_dump_info.cpp", @@ -31,6 +30,8 @@ processdump_sources = [ "process_dumper.cpp", "registers.cpp", "submitter_stack.cpp", + "utils/dump_utils.cpp", + "utils/thread_pool.cpp", ] if (defined(ohos_lite)) { @@ -48,6 +49,7 @@ if (defined(ohos_lite)) { include_dirs = [ ".", + "utils", "$c_utils_include_path", "$faultloggerd_common_path/dfxlog", "$faultloggerd_common_path/dfxutil", @@ -107,6 +109,7 @@ if (defined(ohos_lite)) { include_dirs = [ ".", "coredump", + "utils", "$faultloggerd_interfaces_path/common", "$faultloggerd_interfaces_path/innerkits/backtrace/include", "$faultloggerd_interfaces_path/innerkits/crash_exception", diff --git a/tools/process_dump/decorative_dump_info.h b/tools/process_dump/decorative_dump_info.h index fd7737acc..309cf7edc 100644 --- a/tools/process_dump/decorative_dump_info.h +++ b/tools/process_dump/decorative_dump_info.h @@ -16,6 +16,7 @@ #ifndef DECORATIVE_DUMP_INFO_H #define DECORATIVE_DUMP_INFO_H #include +#include #include #include #include @@ -58,13 +59,6 @@ public: return 0; } - void Symbolize(DfxProcess& process, Unwinder& unwinder) override - { - if (dumpInfo_ != nullptr) { - dumpInfo_->Symbolize(process, unwinder); - } - } - void GetMemoryValues(std::set& memoryValues) override { if (dumpInfo_ != nullptr) { @@ -115,7 +109,6 @@ class OtherThreadDumpInfo : public DecorativeDumpInfo { public: int UnwindStack(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) override; void Print(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) override; - void Symbolize(DfxProcess& process, Unwinder& unwinder) override; static std::shared_ptr CreateInstance() { return std::make_shared(); } }; diff --git a/tools/process_dump/dfx_process.h b/tools/process_dump/dfx_process.h index 199a94aa1..bc2f1b303 100644 --- a/tools/process_dump/dfx_process.h +++ b/tools/process_dump/dfx_process.h @@ -116,7 +116,17 @@ public: { memoryValues_ = memoryValues; } - + + void AddNativeFramesTable(std::pair frame) + { + nativeFramesTable_.emplace(std::move(frame)); + } + + std::map& GetNativeFramesTable() + { + return nativeFramesTable_; + } + void ClearOtherThreads(); pid_t ChangeTid(pid_t tid, bool ns); @@ -135,6 +145,7 @@ private: std::string crashInfoJson_ = ""; pid_t vmPid_ = 0; std::set memoryValues_; + std::map nativeFramesTable_; }; } // namespace HiviewDFX } // namespace OHOS diff --git a/tools/process_dump/dfx_thread.cpp b/tools/process_dump/dfx_thread.cpp index 03d43958a..696aad663 100644 --- a/tools/process_dump/dfx_thread.cpp +++ b/tools/process_dump/dfx_thread.cpp @@ -126,17 +126,20 @@ void DfxThread::SetFrames(const std::vector& frames) frames_ = frames; } -void DfxThread::ParseSymbol(Unwinder& unwinder) +void DfxThread::FillSymbol(const std::map& frameTable) { if (!needParseSymbol_) { return; } - for (auto& frame : frames_) { if (frame.isJsFrame) { // js frame parse in unwinder continue; } - unwinder.ParseFrameSymbol(frame); + auto foundFrame = frameTable.find(frame.pc); + if (foundFrame != frameTable.end() && foundFrame->second.parseSymbolState.IsParseSymbolComplete()) { + frame.funcName = foundFrame->second.funcName; + frame.funcOffset = foundFrame->second.funcOffset; + } } } diff --git a/tools/process_dump/dfx_thread.h b/tools/process_dump/dfx_thread.h index 5bf083d6b..994ae9774 100644 --- a/tools/process_dump/dfx_thread.h +++ b/tools/process_dump/dfx_thread.h @@ -52,7 +52,7 @@ public: { submitterFrames_ = frames; } - void ParseSymbol(Unwinder& unwinder); + void FillSymbol(const std::map& frameTable); std::string ToString(bool needPrintTid = true) const; const DfxThreadInfo& GetThreadInfo() const { diff --git a/tools/process_dump/dump_info.h b/tools/process_dump/dump_info.h index 28935c9c1..88679f304 100644 --- a/tools/process_dump/dump_info.h +++ b/tools/process_dump/dump_info.h @@ -32,7 +32,6 @@ public: virtual void SetDumpInfo(const std::shared_ptr& dumpInfo) {} virtual void Print(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) = 0; virtual int UnwindStack(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) = 0; - virtual void Symbolize(DfxProcess& process, Unwinder& unwinder) = 0; virtual void GetMemoryValues(std::set& memoryValues) {}; }; } diff --git a/tools/process_dump/dump_info_json_formatter.cpp b/tools/process_dump/dump_info_json_formatter.cpp index c59e7f9e2..68e434a15 100644 --- a/tools/process_dump/dump_info_json_formatter.cpp +++ b/tools/process_dump/dump_info_json_formatter.cpp @@ -169,7 +169,7 @@ void DumpInfoJsonFormatter::FillNativeFrameJson(const DfxFrame& frame, Json::Val #else frameJson["pc"] = StringPrintf("%08llx", frame.relPc); #endif - if (frame.parseSymbolState.IsParseSymbolComplete() && frame.funcName.length() <= MAX_FUNC_NAME_LEN) { + if (frame.funcName.length() <= MAX_FUNC_NAME_LEN) { frameJson["symbol"] = frame.funcName; } else { frameJson["symbol"] = ""; diff --git a/tools/process_dump/key_thread_dump_info.cpp b/tools/process_dump/key_thread_dump_info.cpp index a76a339a4..3eded88fd 100644 --- a/tools/process_dump/key_thread_dump_info.cpp +++ b/tools/process_dump/key_thread_dump_info.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "crash_exception.h" #include "decorative_dump_info.h" @@ -78,18 +79,6 @@ bool ParseUnwindStack(const std::vector& stackValues, REGISTER_DUMP_INFO_CLASS(KeyThreadDumpInfo); -void KeyThreadDumpInfo::Symbolize(DfxProcess& process, Unwinder& unwinder) -{ - auto thread = process.GetKeyThread(); - if (thread == nullptr) { - DFXLOGE("key thread is nullptr!"); - return; - } - DFX_TRACE_START("ParseSymbol keyThread:%d", thread->GetThreadInfo().nsTid); - thread->ParseSymbol(unwinder); - DFX_TRACE_FINISH(); -} - void KeyThreadDumpInfo::Print(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) { auto thread = process.GetKeyThread(); @@ -148,6 +137,11 @@ bool KeyThreadDumpInfo::GetKeyThreadStack(DfxProcess& process, Unwinder& unwinde DFX_TRACE_FINISH(); DFX_TRACE_START("KeyThreadGetFrames:%d", tid); thread->SetFrames(unwinder.GetFrames()); + for (const auto& frame : unwinder.GetFrames()) { + if (!frame.isJsFrame) { + process.AddNativeFramesTable(std::make_pair(frame.pc, frame)); + } + } DFX_TRACE_FINISH(); ReportUnwinderException(unwinder.GetLastErrorCode()); UnwindThreadByParseStackIfNeed(thread, unwinder.GetMaps()); diff --git a/tools/process_dump/key_thread_dump_info.h b/tools/process_dump/key_thread_dump_info.h index f2ef6f9c9..2ff21164d 100644 --- a/tools/process_dump/key_thread_dump_info.h +++ b/tools/process_dump/key_thread_dump_info.h @@ -29,7 +29,6 @@ class KeyThreadDumpInfo : public DumpInfo { public: void Print(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) override; int UnwindStack(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) override; - void Symbolize(DfxProcess& process, Unwinder& unwinder) override; static std::shared_ptr CreateInstance() { return std::make_shared(); } private: bool GetKeyThreadStack(DfxProcess& process, Unwinder& unwinder); diff --git a/tools/process_dump/other_thread_dump_info.cpp b/tools/process_dump/other_thread_dump_info.cpp index 1acd9396a..8f10748a2 100644 --- a/tools/process_dump/other_thread_dump_info.cpp +++ b/tools/process_dump/other_thread_dump_info.cpp @@ -19,6 +19,7 @@ #include "dfx_trace.h" #include "process_dump_config.h" #include "dfx_buffer_writer.h" +#include "thread_pool.h" namespace OHOS { namespace HiviewDFX { REGISTER_DUMP_INFO_CLASS(OtherThreadDumpInfo); @@ -51,6 +52,11 @@ int OtherThreadDumpInfo::UnwindStack(DfxProcess& process, const ProcessDumpReque DFX_TRACE_FINISH(); DFX_TRACE_START("OtherThreadGetFrames:%d", tid); thread->SetFrames(unwinder.GetFrames()); + for (const auto& frame : unwinder.GetFrames()) { + if (!frame.isJsFrame) { + process.AddNativeFramesTable(std::make_pair(frame.pc, frame)); + } + } DFX_TRACE_FINISH(); #ifdef PARSE_LOCK_OWNER DumpUtils::ParseLockInfo(unwinder, pid, tid); @@ -72,15 +78,5 @@ void OtherThreadDumpInfo::Print(DfxProcess& process, const ProcessDumpRequest& r } DfxBufferWriter::GetInstance().WriteMsg(dumpInfo); } - -void OtherThreadDumpInfo::Symbolize(DfxProcess& process, Unwinder& unwinder) -{ - DecorativeDumpInfo::Symbolize(process, unwinder); - for (const auto &thread : process.GetOtherThreads()) { - DFX_TRACE_START("ParseSymbol otherThread:%d", thread->GetThreadInfo().nsTid); - thread->ParseSymbol(unwinder); - DFX_TRACE_FINISH(); - } -} } } \ No newline at end of file diff --git a/tools/process_dump/process_dumper.cpp b/tools/process_dump/process_dumper.cpp index 3f6748280..2b0721693 100644 --- a/tools/process_dump/process_dumper.cpp +++ b/tools/process_dump/process_dumper.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -44,7 +43,6 @@ #include "dump_utils.h" #include "dfx_define.h" #include "dfx_dump_request.h" -#include "dfx_dump_res.h" #include "dfx_ptrace.h" #include "dfx_process.h" @@ -63,15 +61,12 @@ #ifndef HISYSEVENT_DISABLE #include "hisysevent.h" #endif -#include "info/fatal_message.h" #include "procinfo.h" #include "reporter.h" #include "unwinder_config.h" #ifndef is_ohos_lite #include "hitrace/hitracechainc.h" -#include "parameters.h" #endif // !is_ohos_lite -#include "info/fatal_message.h" #if defined(__aarch64__) && !defined(is_ohos_lite) #include "coredump_controller.h" #endif @@ -82,8 +77,6 @@ namespace { #undef LOG_TAG #define LOG_DOMAIN 0xD002D11 #define LOG_TAG "DfxProcessDump" -const char *const BLOCK_CRASH_PROCESS = "faultloggerd.priv.block_crash_process.enabled"; -MAYBE_UNUSED const char *const MIXSTACK_ENABLE = "faultloggerd.priv.mixstack.enabled"; const char * const OTHER_THREAD_DUMP_INFO = "OtherThreadDumpInfo"; #if defined(DEBUG_CRASH_LOCAL_HANDLER) @@ -92,96 +85,6 @@ void SigAlarmCallBack() ProcessDumper::GetInstance().ReportSigDumpStats(); } #endif - -static bool IsBlockCrashProcess() -{ -#ifndef is_ohos_lite - static bool isBlockCrash = OHOS::system::GetParameter(BLOCK_CRASH_PROCESS, "false") == "true"; - return isBlockCrash; -#else - return false; -#endif -} - -void WaitForFork(unsigned long pid, unsigned long& childPid) -{ - DFXLOGI("start wait fork event happen"); - int waitStatus = 0; - waitpid(pid, &waitStatus, 0); // wait fork event - DFXLOGI("wait for fork status %{public}d", waitStatus); - if (static_cast(waitStatus) >> 8 == (SIGTRAP | (PTRACE_EVENT_FORK << 8))) { // 8 : get fork event - ptrace(PTRACE_GETEVENTMSG, pid, NULL, &childPid); - DFXLOGI("next child pid %{public}lu", childPid); - waitpid(childPid, &waitStatus, 0); // wait child stop event - } -} - -void GetVmProcessRealPid(const ProcessDumpRequest& request, unsigned long vmPid, int& realPid) -{ - int waitStatus = 0; - ptrace(PTRACE_SETOPTIONS, vmPid, NULL, PTRACE_O_TRACEEXIT); // block son exit - ptrace(PTRACE_CONT, vmPid, NULL, NULL); - - DFXLOGI("start wait exit event happen"); - waitpid(vmPid, &waitStatus, 0); // wait exit stop - long data = ptrace(PTRACE_PEEKDATA, vmPid, reinterpret_cast(request.vmProcRealPidAddr), nullptr); - if (data < 0) { - DFXLOGI("ptrace peek data error %{public}lu %{public}d", vmPid, errno); - } - realPid = static_cast(data); -} - -void ReadPids(const ProcessDumpRequest& request, int& realPid, int& vmPid, DfxProcess process) -{ - unsigned long childPid = 0; - DFX_TRACE_SCOPED("ReadPids"); - WaitForFork(request.tid, childPid); - ptrace(PTRACE_CONT, childPid, NULL, NULL); - - // freeze detach after fork child to fork vm process - if (request.type == ProcessDumpType::DUMP_TYPE_DUMP_CATCH || -#if defined(__aarch64__) && !defined(is_ohos_lite) - CoredumpController::IsCoredumpSignal(request) -#else - false -#endif - ) { - process.Detach(); - DFXLOGI("ptrace detach all tids"); - } - - unsigned long sonPid = 0; - WaitForFork(childPid, sonPid); - vmPid = static_cast(sonPid); - - ptrace(PTRACE_DETACH, childPid, 0, 0); - GetVmProcessRealPid(request, sonPid, realPid); - - DFXLOGI("procecdump get real pid is %{public}d vm pid is %{public}d", realPid, vmPid); -} - -void NotifyOperateResult(ProcessDumpRequest& request, int result) -{ - if (request.childPipeFd[0] != -1) { - close(request.childPipeFd[0]); - request.childPipeFd[0] = -1; - } - if (OHOS_TEMP_FAILURE_RETRY(write(request.childPipeFd[1], &result, sizeof(result))) < 0) { - DFXLOGE("write to child process fail %{public}d", errno); - } -} - -void BlockCrashProcExit(const ProcessDumpRequest& request) -{ - if (!IsBlockCrashProcess()) { - return; - } - DFXLOGI("start block crash process pid %{public}d nspid %{public}d", request.pid, request.nsPid); - if (ptrace(PTRACE_POKEDATA, request.nsPid, reinterpret_cast(request.blockCrashExitAddr), - CRASH_BLOCK_EXIT_FLAG) < 0) { - DFXLOGE("pok block falg to nsPid %{public}d fail %{public}s", request.nsPid, strerror(errno)); - } -} } ProcessDumper &ProcessDumper::GetInstance() @@ -193,7 +96,7 @@ ProcessDumper &ProcessDumper::GetInstance() void ProcessDumper::Dump() { startTime_ = GetTimeMillisec(); - int resDump = DumpProcess(); + DumpErrorCode resDump = DumpProcess(); if (resDump == DumpErrorCode::DUMP_COREDUMP) { return; } @@ -215,17 +118,17 @@ void ProcessDumper::Dump() if (request_.type == ProcessDumpType::DUMP_TYPE_CPP_CRASH) { DumpUtils::InfoCrashUnwindResult(request_, resDump == DumpErrorCode::DUMP_ESUCCESS); - BlockCrashProcExit(request_); + DumpUtils::BlockCrashProcExit(request_); } if (process_ != nullptr) { process_->Detach(); } } -int ProcessDumper::DumpProcess() +DumpErrorCode ProcessDumper::DumpProcess() { DFX_TRACE_SCOPED("DumpProcess"); - int dumpRes = ReadRequestAndCheck(); + DumpErrorCode dumpRes = ReadRequestAndCheck(); if (dumpRes != DumpErrorCode::DUMP_ESUCCESS) { return dumpRes; } @@ -242,25 +145,63 @@ int ProcessDumper::DumpProcess() "threadname(%{public}s).", request_.siginfo.si_value.sival_int, request_.pid, request_.nsPid, request_.tid, request_.threadName); SetProcessdumpTimeout(request_.siginfo); - UpdateConfigByRequest(); - if (!InitDfxProcess()) { - DFXLOGE("Failed to init crash process info."); - dumpRes = DumpErrorCode::DUMP_EATTACH; - return dumpRes; - } - if (!InitUnwinder(dumpRes)) { + dumpRes = DumpPreparation(); + if (dumpRes != DumpErrorCode::DUMP_ESUCCESS) { return dumpRes; } - if (!InitBufferWriter()) { - DFXLOGE("Failed to init buffer writer."); - dumpRes = DumpErrorCode::DUMP_EGETFD; - } PrintDumpInfo(dumpRes); UnwindWriteJit(); DfxPtrace::Detach(process_->GetVmPid()); return dumpRes; } +void ProcessDumper::AsyncInitialization() +{ + if (isCoreDump_) { + return; + } + std::promise initUnwinderFinish; + initUnwinderFinishFuture_ = initUnwinderFinish.get_future(); + initTask_ = std::async(std::launch::async, [this, initFinish = std::move(initUnwinderFinish)] () mutable { + DumpErrorCode dumpRes = DumpErrorCode::DUMP_ESUCCESS; + if (!InitUnwinder(dumpRes)) { + initFinish.set_value(); + return dumpRes; + } + initFinish.set_value(); + if (!InitBufferWriter()) { + DFXLOGE("Failed to init buffer writer."); + return DumpErrorCode::DUMP_EGETFD; + } + return dumpRes; + }); +} + +DumpErrorCode ProcessDumper::DumpPreparation() +{ + UpdateConfigByRequest(); + if (!InitDfxProcess()) { + DFXLOGE("Failed to init crash process info."); + return DumpErrorCode::DUMP_EATTACH; + } + AsyncInitialization(); + if (ReadVmPid() <= 0) { + ReportCrashException(CrashExceptionCode::CRASH_DUMP_EREADPID); + DFXLOGE("Failed to read vm pid!"); + return DumpErrorCode::DUMP_EREADPID; + } +#if defined(__aarch64__) && !defined(is_ohos_lite) + if (isCoreDump_) { + coredumpManager_->DumpMemoryForPid(process_->GetVmPid()); + return DumpErrorCode::DUMP_COREDUMP; + } +#endif + if (initTask_.valid()) { + return initTask_.get(); // wait init task finish + } + return DumpErrorCode::DUMP_ESUCCESS; +} + void ProcessDumper::SetProcessdumpTimeout(siginfo_t &si) { if (si.si_signo != SIGDUMP) { @@ -326,13 +267,13 @@ void ProcessDumper::FormatJsonInfoIfNeed() DFXLOGI("Finish GetJsonFormatInfo len %{public}" PRIuPTR "", jsonInfo.length()); } -void ProcessDumper::WriteDumpResIfNeed(int32_t resDump) +void ProcessDumper::WriteDumpResIfNeed(const DumpErrorCode& resDump) { DFXLOGI("dump result: %{public}s", DfxDumpRes::ToString(resDump).c_str()); if (request_.siginfo.si_signo != SIGDUMP) { return; } - if (!DfxBufferWriter::GetInstance().WriteDumpRes(resDump)) { // write dump res, retry request_ pipefd + if (!DfxBufferWriter::GetInstance().WriteDumpRes(resDump)) { // write dump res, retry request pipefd int pipeWriteFd[] = { -1, -1 }; if (RequestPipeFd(request_.pid, FaultLoggerPipeType::PIPE_FD_WRITE, pipeWriteFd) == -1) { DFXLOGE("%{public}s request_ pipe failed, err:%{public}d", __func__, errno); @@ -345,7 +286,7 @@ void ProcessDumper::WriteDumpResIfNeed(int32_t resDump) } } -int32_t ProcessDumper::ReadRequestAndCheck() +DumpErrorCode ProcessDumper::ReadRequestAndCheck() { DFX_TRACE_SCOPED("ReadRequestAndCheck"); ElapsedTime counter("ReadRequestAndCheck", 20); // 20 : limit cost time 20 ms @@ -378,9 +319,6 @@ void ProcessDumper::UpdateConfigByRequest() OTHER_THREAD_DUMP_INFO), dumpInfoComponent.end()); auto config = ProcessDumpConfig::GetInstance().GetConfig(); config.dumpInfo[request_.type] = dumpInfoComponent; - for (const auto& info : dumpInfoComponent) { - DFXLOGI("component%{public}s.", info.c_str()); - } ProcessDumpConfig::GetInstance().SetConfig(std::move(config)); } isJsonDump_ = request_.siginfo.si_code == DUMP_TYPE_REMOTE_JSON; @@ -414,7 +352,7 @@ void ProcessDumper::UnwindWriteJit() } } -void ProcessDumper::PrintDumpInfo(int& dumpRes) +void ProcessDumper::PrintDumpInfo(DumpErrorCode& dumpRes) { DFX_TRACE_SCOPED("PrintDumpInfo"); if (process_ == nullptr || unwinder_ == nullptr) { @@ -444,35 +382,24 @@ void ProcessDumper::PrintDumpInfo(int& dumpRes) if (threadDumpInfo != nullptr) { int unwindSuccessCnt = threadDumpInfo->UnwindStack(*process_, request_, *unwinder_); DFXLOGI("unwind success thread count(%{public}d)", unwindSuccessCnt); - if (unwindSuccessCnt > 0) { - dumpRes = ParseSymbols(threadDumpInfo); - } else { - dumpRes = DumpErrorCode::DUMP_ESTOPUNWIND; - DFXLOGE("Failed to unwind process."); - } + dumpRes = unwindSuccessCnt > 0 ? ConcurrentSymbolize() : DumpErrorCode::DUMP_ESTOPUNWIND; } - if (dumpInfo != nullptr && !isJsonDump_) { // isJsonDump_ will print after format json dumpInfo->Print(*process_, request_, *unwinder_); } } -int ProcessDumper::ParseSymbols(std::shared_ptr threadDumpInfo) +DumpErrorCode ProcessDumper::WaitParseSymbols() { uint64_t curTime = GetAbsTimeMilliSeconds(); uint32_t lessRemainTimeMs = static_cast(ProcessDumpConfig::GetInstance().GetConfig().reservedParseSymbolTime); - int dumpRes = 0; + DumpErrorCode dumpRes = DumpErrorCode::DUMP_ESUCCESS; if (request_.type != ProcessDumpType::DUMP_TYPE_DUMP_CATCH || expectedDumpFinishTime_ == 0) { - threadDumpInfo->Symbolize(*process_, *unwinder_); + threadPool_.Stop(); } else if (expectedDumpFinishTime_ > curTime && expectedDumpFinishTime_ - curTime > lessRemainTimeMs) { - parseSymbolTask_ = std::async(std::launch::async, [threadDumpInfo, this]() { - DFX_TRACE_SCOPED("parse symbol task"); - threadDumpInfo->Symbolize(*process_, *unwinder_); - }); uint64_t waitTime = expectedDumpFinishTime_ - curTime - lessRemainTimeMs; - if (parseSymbolTask_.wait_for(std::chrono::milliseconds(waitTime)) != std::future_status::ready) { - DFXLOGW("Parse symbol timeout"); + if (!threadPool_.StopWithTimeOut(waitTime)) { dumpRes = DumpErrorCode::DUMP_ESYMBOL_PARSE_TIMEOUT; } } else { @@ -483,35 +410,60 @@ int ProcessDumper::ParseSymbols(std::shared_ptr threadDumpInfo) return dumpRes; } -bool ProcessDumper::InitUnwinder(int &dumpRes) +DumpErrorCode ProcessDumper::ConcurrentSymbolize() +{ + DumpErrorCode dumpRes = DumpErrorCode::DUMP_ESTOPUNWIND; + if (process_ == nullptr || process_->GetNativeFramesTable().empty()) { + return dumpRes; + } + constexpr size_t threadPoolCapacity = 3; + threadPool_.Start(threadPoolCapacity); + auto left = process_->GetNativeFramesTable().begin(); // left boundary of the sliding window + auto end = process_->GetNativeFramesTable().end(); + auto right = left; + while (left != end || right != end) { // Both left and right should move to the end + // if map of right boundary of the sliding window equal to left, right boundary moves right one step + if (left != end && right != end && left->second.map == right->second.map) { + right++; + continue; + } + // if not equal, add element of the sliding window to task + auto task = std::bind([this, left, right] () mutable { + DFX_TRACE_SCOPED("ParseSymbol:%s", left->second.mapName.c_str()); + while (left != right) { + unwinder_->ParseFrameSymbol(left->second); + left++; + } + }); + threadPool_.AddTask(task); + left = right; // left moves to the location of right + } + dumpRes = WaitParseSymbols(); + auto keyThread = process_->GetKeyThread(); + if (keyThread != nullptr) { + keyThread->FillSymbol(process_->GetNativeFramesTable()); + } + for (const auto &thread : process_->GetOtherThreads()) { + if (thread != nullptr) { + thread->FillSymbol(process_->GetNativeFramesTable()); + } + } + return dumpRes; +} + +bool ProcessDumper::InitUnwinder(DumpErrorCode &dumpRes) { DFX_TRACE_SCOPED("InitUnwinder"); if (process_ == nullptr) { DFXLOGE("Failed to read real pid!"); return false; } - pid_t realPid = 0; - pid_t vmPid = 0; - ReadPids(request_, realPid, vmPid, *process_); - if (realPid <= 0 || vmPid <= 0) { - ReportCrashException(CrashExceptionCode::CRASH_DUMP_EREADPID); - DFXLOGE("Failed to read real pid!"); - dumpRes = DumpErrorCode::DUMP_EREADPID; - return false; - } -#if defined(__aarch64__) && !defined(is_ohos_lite) - if (coredumpManager_) { - coredumpManager_->DumpMemoryForPid(vmPid); - dumpRes = DumpErrorCode::DUMP_COREDUMP; - return false; // coredump flow end - } -#endif - process_->SetVmPid(vmPid); #if defined(PROCESSDUMP_MINIDEBUGINFO) UnwinderConfig::SetEnableMiniDebugInfo(true); UnwinderConfig::SetEnableLoadSymbolLazily(true); #endif - unwinder_ = std::make_shared(realPid, vmPid, request_.type != ProcessDumpType::DUMP_TYPE_DUMP_CATCH); + bool crash = request_.type != ProcessDumpType::DUMP_TYPE_DUMP_CATCH; + unwinder_ = std::make_shared(request_.pid, request_.nsPid, crash); unwinder_->EnableParseNativeSymbol(false); if (unwinder_->GetMaps() == nullptr) { ReportCrashException(CrashExceptionCode::CRASH_LOG_EMAPLOS); @@ -541,33 +493,56 @@ bool ProcessDumper::InitDfxProcess() process_ = std::make_shared(); process_->InitProcessInfo(request_.pid, request_.nsPid, request_.uid, std::string(request_.processName)); if (!process_->InitKeyThread(request_)) { - NotifyOperateResult(request_, OPE_FAIL); + DumpUtils::NotifyOperateResult(request_, OPE_FAIL); return false; } + DFXLOGI("Init key thread successfully."); #if defined(__aarch64__) && !defined(is_ohos_lite) if (CoredumpController::IsCoredumpAllowed(request_)) { coredumpManager_ = std::make_unique(); coredumpManager_->ProcessRequest(request_); + isCoreDump_ = true; } #endif - DFXLOGI("Init key thread successfully."); - NotifyOperateResult(request_, OPE_SUCCESS); - ptrace(PTRACE_SETOPTIONS, request_.tid, NULL, PTRACE_O_TRACEFORK); - ptrace(PTRACE_CONT, request_.tid, 0, 0); - + DumpUtils::NotifyOperateResult(request_, OPE_SUCCESS); auto dumpInfoComp = FindDumpInfoByType(request_.type); if (std::find(dumpInfoComp.begin(), dumpInfoComp.end(), OTHER_THREAD_DUMP_INFO) != dumpInfoComp.end()) { process_->InitOtherThreads(request_.tid); } DFXLOGI("Finish create all thread."); #if defined(__aarch64__) && !defined(is_ohos_lite) - if (coredumpManager_) { + if (isCoreDump_) { coredumpManager_->TriggerCoredump(); } #endif return true; } +int ProcessDumper::ReadVmPid() +{ + unsigned long childPid = 0; + DFX_TRACE_SCOPED("ReadVmPid"); + ptrace(PTRACE_SETOPTIONS, request_.tid, NULL, PTRACE_O_TRACEFORK); + ptrace(PTRACE_CONT, request_.tid, 0, 0); + DumpUtils::WaitForFork(request_.tid, childPid); + ptrace(PTRACE_CONT, childPid, NULL, NULL); + // freeze and coredump detach target processdump after fork child to fork vm process + if (request_.type == ProcessDumpType::DUMP_TYPE_DUMP_CATCH || isCoreDump_) { + if (initUnwinderFinishFuture_.valid()) { + initUnwinderFinishFuture_.get(); + } + process_->Detach(); + DFXLOGI("ptrace detach all tids"); + } + unsigned long sonPid = 0; + DumpUtils::WaitForFork(childPid, sonPid); + int vmPid = static_cast(sonPid); + ptrace(PTRACE_DETACH, childPid, 0, 0); + process_->SetVmPid(vmPid); + DFXLOGI("processdump get vm pid is %{public}d", vmPid); + return vmPid; +} + int ProcessDumper::GeFaultloggerdRequestType() { switch (request_.siginfo.si_signo) { diff --git a/tools/process_dump/process_dumper.h b/tools/process_dump/process_dumper.h index 4df89b515..b8d70af59 100644 --- a/tools/process_dump/process_dumper.h +++ b/tools/process_dump/process_dumper.h @@ -29,9 +29,11 @@ #include "coredump_manager.h" #endif #include "dfx_dump_request.h" +#include "dfx_dump_res.h" #include "dfx_process.h" #include "dump_info.h" #include "nocopyable.h" +#include "thread_pool.h" #include "unwinder.h" namespace OHOS { @@ -50,34 +52,41 @@ public: private: ProcessDumper() = default; DISALLOW_COPY_AND_MOVE(ProcessDumper); - int DumpProcess(); - int32_t ReadRequestAndCheck(); + DumpErrorCode DumpProcess(); + DumpErrorCode ReadRequestAndCheck(); bool InitBufferWriter(); bool InitDfxProcess(); - bool InitUnwinder(int &dumpRes); + bool InitUnwinder(DumpErrorCode &dumpRes); int GeFaultloggerdRequestType(); void UnwindWriteJit(); void FormatJsonInfoIfNeed(); void UpdateConfigByRequest(); - void WriteDumpResIfNeed(int32_t resDump); - void PrintDumpInfo(int& dumpRes); - int ParseSymbols(std::shared_ptr threadDumpInfo); + void WriteDumpResIfNeed(const DumpErrorCode& resDump); + void PrintDumpInfo(DumpErrorCode& dumpRes); + DumpErrorCode WaitParseSymbols(); std::vector FindDumpInfoByType(const ProcessDumpType& dumpType); int32_t CreateFileForCrash(int32_t pid, uint64_t time) const; void RemoveFileIfNeed(const std::string& dirPath) const; + int ReadVmPid(); + void AsyncInitialization(); + DumpErrorCode ConcurrentSymbolize(); + DumpErrorCode DumpPreparation(); private: void SetProcessdumpTimeout(siginfo_t &si); std::shared_ptr process_ = nullptr; std::shared_ptr unwinder_ = nullptr; + ThreadPool threadPool_; ProcessDumpRequest request_{}; uint64_t startTime_ = 0; uint64_t finishTime_ = 0; static constexpr size_t DEFAULT_MAX_STRING_LEN = 2048; bool isJsonDump_ = false; + bool isCoreDump_ = false; uint64_t expectedDumpFinishTime_ = 0; - std::future parseSymbolTask_; + std::future initTask_; + std::future initUnwinderFinishFuture_; #if defined(__aarch64__) && !defined(is_ohos_lite) std::unique_ptr coredumpManager_; #endif diff --git a/tools/process_dump/reporter.cpp b/tools/process_dump/reporter.cpp index 487844a2f..d32902355 100644 --- a/tools/process_dump/reporter.cpp +++ b/tools/process_dump/reporter.cpp @@ -72,17 +72,20 @@ void CppCrashReporter::Report(DfxProcess& process, const ProcessDumpRequest &req void CppCrashReporter::ReportToHiview(DfxProcess& process, const ProcessDumpRequest &request) { - void* handle = dlopen("libfaultlogger.z.so", RTLD_LAZY | RTLD_NODELETE); + std::shared_ptr handle(dlopen("libfaultlogger.z.so", RTLD_LAZY | RTLD_NODELETE), [] (void* handle) { + if (handle != nullptr) { + dlclose(handle); + } + }); if (handle == nullptr) { DFXLOGW("Failed to dlopen libfaultlogger, %{public}s\n", dlerror()); dlerror(); return; } - auto addFaultLog = reinterpret_cast(dlsym(handle, "AddFaultLog")); + auto addFaultLog = reinterpret_cast(dlsym(handle.get(), "AddFaultLog")); if (addFaultLog == nullptr) { DFXLOGW("Failed to dlsym AddFaultLog, %{public}s\n", dlerror()); dlerror(); - dlclose(handle); return; } FaultDFXLOGIInner info; @@ -100,7 +103,6 @@ void CppCrashReporter::ReportToHiview(DfxProcess& process, const ProcessDumpRequ addFaultLog(&info); DFXLOGI("Finish report fault to FaultLogger %{public}s(%{public}d,%{public}d)", info.module.c_str(), info.pid, info.id); - dlclose(handle); } std::string CppCrashReporter::GetSummary(DfxProcess& process) @@ -159,23 +161,25 @@ SmartFd CppCrashReporter::TranferCrashInfoToHiview(const std::string& cppCrashIn void CppCrashReporter::ReportToAbilityManagerService(const DfxProcess& process) { - void* handle = dlopen("libability_manager_c.z.so", RTLD_LAZY | RTLD_NODELETE); + std::shared_ptr handle(dlopen("libability_manager_c.z.so", RTLD_LAZY | RTLD_NODELETE), [] (void* handle) { + if (handle != nullptr) { + dlclose(handle); + } + }); if (handle == nullptr) { DFXLOGW("Failed to dlopen libabilityms, %{public}s\n", dlerror()); return; } - RecordAppExitReason recordAppExitReason = (RecordAppExitReason)dlsym(handle, "RecordAppExitReason"); + RecordAppExitReason recordAppExitReason = (RecordAppExitReason)dlsym(handle.get(), "RecordAppExitReason"); if (recordAppExitReason == nullptr) { DFXLOGW("Failed to dlsym RecordAppExitReason, %{public}s\n", dlerror()); - dlclose(handle); return; } // defined in interfaces/inner_api/ability_manager/include/ability_state.h const int cppCrashExitReason = 2; recordAppExitReason(cppCrashExitReason, process.GetReason().c_str()); - dlclose(handle); #ifndef HISYSEVENT_DISABLE int result = HiSysEventWrite(HiSysEvent::Domain::FRAMEWORK, "PROCESS_KILL", HiSysEvent::EventType::FAULT, "PID", process.GetProcessInfo().pid, "PROCESS_NAME", process.GetProcessInfo().processName.c_str(), diff --git a/tools/process_dump/dump_utils.cpp b/tools/process_dump/utils/dump_utils.cpp similarity index 70% rename from tools/process_dump/dump_utils.cpp rename to tools/process_dump/utils/dump_utils.cpp index ae642e291..b783fa1d1 100644 --- a/tools/process_dump/dump_utils.cpp +++ b/tools/process_dump/utils/dump_utils.cpp @@ -16,22 +16,26 @@ #include #include -#include "sys/ptrace.h" +#include +#include -#include "dfx_util.h" -#include "dfx_log.h" -#include "dfx_kernel_stack.h" #include "dfx_frame_formatter.h" +#include "dfx_kernel_stack.h" +#include "dfx_log.h" +#include "dfx_trace.h" +#include "dfx_util.h" #ifndef is_ohos_lite #include "bundle_mgr_interface.h" #include "bundle_mgr_proxy.h" #include "if_system_ability_manager.h" #include "iservice_registry.h" +#include "parameters.h" #include "system_ability_definition.h" #endif namespace OHOS { namespace HiviewDFX { namespace { +const char *const BLOCK_CRASH_PROCESS = "faultloggerd.priv.block_crash_process.enabled"; // defined in alltypes.h #define DFX_MUTEX_TYPE u.i[0] #define DFX_MUTEX_OWNER u.vi[1] @@ -207,5 +211,71 @@ void DumpUtils::InfoCrashUnwindResult(const ProcessDumpRequest& request, bool is DFXLOGE("pok unwind success flag to nsPid %{public}d fail %{public}s", request.nsPid, strerror(errno)); } } + +bool IsBlockCrashProcess() +{ +#ifndef is_ohos_lite + static bool isBlockCrash = OHOS::system::GetParameter(BLOCK_CRASH_PROCESS, "false") == "true"; + return isBlockCrash; +#else + return false; +#endif +} + +void DumpUtils::WaitForFork(unsigned long pid, unsigned long& childPid) +{ + DFXLOGI("start wait fork event happen"); + int waitStatus = 0; + waitpid(pid, &waitStatus, 0); // wait fork event + DFXLOGI("wait for fork status %{public}d", waitStatus); + if (static_cast(waitStatus) >> 8 == (SIGTRAP | (PTRACE_EVENT_FORK << 8))) { // 8 : get fork event + ptrace(PTRACE_GETEVENTMSG, pid, NULL, &childPid); + DFXLOGI("next child pid %{public}lu", childPid); + waitpid(childPid, &waitStatus, 0); // wait child stop event + } +} + +void DumpUtils::GetVmProcessRealPid(const ProcessDumpRequest& request, unsigned long vmPid, int& realPid) +{ + int waitStatus = 0; + ptrace(PTRACE_SETOPTIONS, vmPid, NULL, PTRACE_O_TRACEEXIT); // block son exit + ptrace(PTRACE_CONT, vmPid, NULL, NULL); + + DFXLOGI("start wait exit event happen"); + waitpid(vmPid, &waitStatus, 0); // wait exit stop + long data = ptrace(PTRACE_PEEKDATA, vmPid, reinterpret_cast(request.vmProcRealPidAddr), nullptr); + if (data < 0) { + DFXLOGI("ptrace peek data error %{public}lu %{public}d", vmPid, errno); + return; + } + realPid = static_cast(data); +} + +void DumpUtils::NotifyOperateResult(ProcessDumpRequest& request, int result) +{ + if (request.childPipeFd[0] != -1) { + close(request.childPipeFd[0]); + request.childPipeFd[0] = -1; + } + if (OHOS_TEMP_FAILURE_RETRY(write(request.childPipeFd[1], &result, sizeof(result))) < 0) { + DFXLOGE("write to child process fail %{public}d", errno); + } + if (request.childPipeFd[1] != -1) { + close(request.childPipeFd[1]); + request.childPipeFd[1] = -1; + } +} + +void DumpUtils::BlockCrashProcExit(const ProcessDumpRequest& request) +{ + if (!IsBlockCrashProcess()) { + return; + } + DFXLOGI("start block crash process pid %{public}d nspid %{public}d", request.pid, request.nsPid); + if (ptrace(PTRACE_POKEDATA, request.nsPid, reinterpret_cast(request.blockCrashExitAddr), + CRASH_BLOCK_EXIT_FLAG) < 0) { + DFXLOGE("pok block falg to nsPid %{public}d fail %{public}s", request.nsPid, strerror(errno)); + } +} } // namespace HiviewDFX } // namespace OHOS diff --git a/tools/process_dump/dump_utils.h b/tools/process_dump/utils/dump_utils.h similarity index 78% rename from tools/process_dump/dump_utils.h rename to tools/process_dump/utils/dump_utils.h index 63e838a67..dc7d799e2 100644 --- a/tools/process_dump/dump_utils.h +++ b/tools/process_dump/utils/dump_utils.h @@ -17,6 +17,7 @@ #define DUMP_UTILS_H #include "unwinder.h" #include "dfx_dump_request.h" +#include "dfx_process.h" #include "dfx_thread.h" #include #include @@ -32,6 +33,10 @@ public: static bool ReadTargetMemory(pid_t tid, uintptr_t addr, uintptr_t &value); static std::string GetSelfBundleName(); static void InfoCrashUnwindResult(const ProcessDumpRequest& request, bool isUnwindSucc); + static void BlockCrashProcExit(const ProcessDumpRequest& request); + static void WaitForFork(unsigned long pid, unsigned long& childPid); + static void GetVmProcessRealPid(const ProcessDumpRequest& request, unsigned long vmPid, int& realPid); + static void NotifyOperateResult(ProcessDumpRequest& request, int result); }; } // namespace HiviewDFX } // namespace OHOS diff --git a/tools/process_dump/utils/thread_pool.cpp b/tools/process_dump/utils/thread_pool.cpp new file mode 100644 index 000000000..2e3355248 --- /dev/null +++ b/tools/process_dump/utils/thread_pool.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thread_pool.h" +#include +#include "dfx_log.h" +#include "dfx_define.h" +#include "dfx_util.h" +namespace OHOS { +namespace HiviewDFX { +void ThreadPool::Start(size_t threadPoolCapacity) +{ + for (size_t i = 0; i < threadPoolCapacity; ++i) { + workers_.emplace_back([this] { + std::function task; + while (TakeTask(task)) { + task(); + completeTaskCount_++; + } + }); + } +} + +void ThreadPool::AddTask(const std::function &task) +{ + { + std::unique_lock lock(queueMutex_); + if (stop_) { + return; + } + tasks_.emplace_back(task); + } + condition_.notify_one(); +} + +bool ThreadPool::TakeTask(std::function &task) +{ + std::unique_lock lock(queueMutex_); + condition_.wait(lock, [this] { + return stop_ || !tasks_.empty(); + }); + if (stop_ && tasks_.empty()) { + return false; + } + task = std::move(tasks_.front()); + tasks_.pop_front(); + return true; +} + +bool ThreadPool::StopWithTimeOut(uint64_t waitTimeOutMs) +{ + bool completeTask = false; + uint64_t beginTime = GetAbsTimeMilliSeconds(); + uint64_t curTime = beginTime; + while (curTime - beginTime < waitTimeOutMs) { + if (completeTaskCount_ == taskNum_) { + completeTask = true; + break; + } + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 1000000; // 1000000 : 1ms + OHOS_TEMP_FAILURE_RETRY(nanosleep(&ts, &ts)); + curTime = GetAbsTimeMilliSeconds(); + } + completeTask = completeTaskCount_ == taskNum_; + { + std::unique_lock lock(queueMutex_); + tasks_.clear(); + stop_ = true; + } + condition_.notify_all(); + for (auto &worker : workers_) { + worker.detach(); + } + return completeTask; +} + +void ThreadPool::Stop() +{ + { + std::unique_lock lock(queueMutex_); + if (stop_) { + return; + } + stop_ = true; + } + condition_.notify_all(); + for (auto &worker : workers_) { + worker.join(); + } +} + +ThreadPool::~ThreadPool() +{ + if (!stop_) { + Stop(); + } +} +} // namespace HiviewDFX +} // namespace OHOS \ No newline at end of file diff --git a/tools/process_dump/utils/thread_pool.h b/tools/process_dump/utils/thread_pool.h new file mode 100644 index 000000000..6de8a8e08 --- /dev/null +++ b/tools/process_dump/utils/thread_pool.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_POOL_H +#define THREAD_POOL_H +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS { +namespace HiviewDFX { +class ThreadPool { +public: + ThreadPool() : completeTaskCount_(0), taskNum_(0) {}; + void Start(size_t threadPoolCapacity); + void AddTask(const std::function &task); + bool StopWithTimeOut(uint64_t waitTimeOutMs = 0); + void Stop(); + ~ThreadPool(); +private: + DISALLOW_COPY_AND_MOVE(ThreadPool); + bool TakeTask(std::function &task); + std::vector workers_; + std::deque> tasks_; + std::mutex queueMutex_; + std::condition_variable condition_; + std::atomic completeTaskCount_; + size_t taskNum_; + bool stop_ = false; +}; +} // namespace HiviewDFX +} // namespace OHOS +#endif \ No newline at end of file -- Gitee