diff --git a/OAT.xml b/OAT.xml index 790c1717a4b39925a0a3cbc9d5bd9c4532e9acd7..25a6918d8e1887b07690848ebb1549fa908c3fcb 100644 --- a/OAT.xml +++ b/OAT.xml @@ -78,6 +78,8 @@ Note:If the text contains special characters, please escape them according to th + + @@ -91,6 +93,8 @@ Note:If the text contains special characters, please escape them according to th + + diff --git a/common/cutil/dfx_cutil.c b/common/cutil/dfx_cutil.c index 3a36b13db422d23cdbc544d857a3407c1251b66a..14b1be1598f94709f52321038b43a90319860583 100644 --- a/common/cutil/dfx_cutil.c +++ b/common/cutil/dfx_cutil.c @@ -86,22 +86,6 @@ uint64_t GetTimeMilliseconds(void) (((uint64_t)ts.tv_nsec) / NUMBER_ONE_MILLION); // 1000000 : nanosecond to millisecond convert ratio } -bool TrimAndDupStr(const char* src, char* dst) -{ - if (src == NULL || dst == NULL) { - return false; - } - - for (char ch = *src; ch != '\0' && ch != '\n';) { - if (ch != ' ') { - *dst++ = ch; - } - ch = *++src; - } - *dst = '\0'; - return true; -} - uint64_t GetAbsTimeMilliSecondsCInterce(void) { struct timespec ts; diff --git a/common/cutil/dfx_cutil.h b/common/cutil/dfx_cutil.h index 8863644fa2deccb7724ee46dff417aed4dc0675e..c2e5325d8130f2ea0f25566b04f81d55ce3cd8d0 100644 --- a/common/cutil/dfx_cutil.h +++ b/common/cutil/dfx_cutil.h @@ -34,8 +34,6 @@ AT_SYMBOL_HIDDEN bool GetProcessName(char* buffer, size_t bufferSz); AT_SYMBOL_HIDDEN uint64_t GetTimeMilliseconds(void); -AT_SYMBOL_HIDDEN bool TrimAndDupStr(const char* src, char* dst); - AT_SYMBOL_HIDDEN uint64_t GetAbsTimeMilliSecondsCInterce(void); AT_SYMBOL_HIDDEN void ParseSiValue(const siginfo_t* si, uint64_t* endTime, int* tid); diff --git a/common/dfxutil/proc_util.cpp b/common/dfxutil/proc_util.cpp index a3180d693dc07763209dc61ddb08455db9571f28..b96707b5180d6afa980016c7e9742d5b0eadabe7 100644 --- a/common/dfxutil/proc_util.cpp +++ b/common/dfxutil/proc_util.cpp @@ -45,7 +45,6 @@ bool Schedstat::ParseSchedstat(const std::string& schedstatPath) { char realPath[PATH_MAX] = {0}; if (realpath(schedstatPath.c_str(), realPath) == nullptr) { - DFXLOGE("path invalid. %{public}s", schedstatPath.c_str()); return false; } @@ -104,6 +103,7 @@ bool ThreadInfo::ParserThreadInfo(pid_t tid) ProcessInfo info; if (!ParseProcInfo(tid, info)) { + DFXLOGE("read %{public}d info failed.", tid); return false; } @@ -222,7 +222,6 @@ bool ParseStat(const std::string& statPath, ProcessInfo& info) { char realPath[PATH_MAX] = {0}; if (realpath(statPath.c_str(), realPath) == nullptr) { - DFXLOGE("path invalid. %{public}s", statPath.c_str()); return false; } diff --git a/common/dfxutil/smart_fd.h b/common/dfxutil/smart_fd.h index f24d67f43ee83777064f889f9f0f5ab7ad657f8a..6eb414ae5bb989bf612400ce36ec1060a4527eff 100644 --- a/common/dfxutil/smart_fd.h +++ b/common/dfxutil/smart_fd.h @@ -27,9 +27,11 @@ public: SmartFd() = default; explicit SmartFd(int fd, bool fdsan = true) : fd_(fd), fdsan_(fdsan) { +#ifndef is_host if (fd_ >= 0 && fdsan_) { fdsan_exchange_owner_tag(fd_, 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, DFX_FDSAN_DOMAIN)); } +#endif // is_host } ~SmartFd() @@ -84,10 +86,12 @@ private: if (fd_ < 0) { return; } +#ifndef is_host if (fdsan_) { fdsan_close_with_tag(fd_, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, DFX_FDSAN_DOMAIN)); return; } +#endif // is_host close(fd_); } diff --git a/interfaces/innerkits/dump_catcher/lite_perf.cpp b/interfaces/innerkits/dump_catcher/lite_perf.cpp index 0b89c8ff117770d9c8cbf08171a0c8ed9ea267d9..c1bfd55c1cde004b2c637efacbcee55c6ef9bec0 100644 --- a/interfaces/innerkits/dump_catcher/lite_perf.cpp +++ b/interfaces/innerkits/dump_catcher/lite_perf.cpp @@ -300,9 +300,9 @@ int LitePerf::Impl::ExecDump(const std::vector& tids, int freq, int duratio } pid_t pid = 0; - pid = vfork(); + pid = fork(); if (pid < 0) { - DFXLOGE("Failed to vfork."); + DFXLOGE("Failed to fork."); return -1; } if (pid == 0) { @@ -312,9 +312,9 @@ int LitePerf::Impl::ExecDump(const std::vector& tids, int freq, int duratio _exit(-1); } - pid_t dumpPid = vfork(); + pid_t dumpPid = fork(); if (dumpPid < 0) { - DFXLOGE("Failed to vfork."); + DFXLOGE("Failed to fork."); _exit(-1); } if (dumpPid == 0) { diff --git a/interfaces/innerkits/formatter/dfx_json_formatter.cpp b/interfaces/innerkits/formatter/dfx_json_formatter.cpp index ac349891bac541a3055b61ea8456da37a51cb195..477d733883e87d2dc68c4f6dd3ea432507390c57 100644 --- a/interfaces/innerkits/formatter/dfx_json_formatter.cpp +++ b/interfaces/innerkits/formatter/dfx_json_formatter.cpp @@ -27,6 +27,14 @@ namespace HiviewDFX { #ifndef is_ohos_lite namespace { const int FRAME_BUF_LEN = 1024; +static std::string JsonAsString(const Json::Value& val) +{ + if (val.isConvertibleTo(Json::stringValue)) { + return val.asString(); + } + return ""; +} + static bool FormatJsFrame(const Json::Value& frames, const uint32_t& frameIdx, std::string& outStr) { const int jsIdxLen = 10; @@ -36,18 +44,18 @@ static bool FormatJsFrame(const Json::Value& frames, const uint32_t& frameIdx, s return false; } outStr = std::string(buf); - std::string symbol = frames[frameIdx]["symbol"].asString(); + std::string symbol = JsonAsString(frames[frameIdx]["symbol"]); if (!symbol.empty()) { outStr.append(" " + symbol); } - std::string packageName = frames[frameIdx]["packageName"].asString(); + std::string packageName = JsonAsString(frames[frameIdx]["packageName"]); if (!packageName.empty()) { outStr.append(" " + packageName); } - std::string file = frames[frameIdx]["file"].asString(); + std::string file = JsonAsString(frames[frameIdx]["file"]); if (!file.empty()) { - std::string line = frames[frameIdx]["line"].asString(); - std::string column = frames[frameIdx]["column"].asString(); + std::string line = JsonAsString(frames[frameIdx]["line"]); + std::string column = JsonAsString(frames[frameIdx]["column"]); outStr.append(" (" + file + ":" + line + ":" + column + ")"); } return true; @@ -57,11 +65,11 @@ static bool FormatNativeFrame(const Json::Value& frames, const uint32_t& frameId { char buf[FRAME_BUF_LEN] = {0}; char format[] = "#%02u pc %s %s"; - std::string buildId = frames[frameIdx]["buildId"].asString(); - std::string file = frames[frameIdx]["file"].asString(); - std::string offset = frames[frameIdx]["offset"].asString(); - std::string pc = frames[frameIdx]["pc"].asString(); - std::string symbol = frames[frameIdx]["symbol"].asString(); + std::string buildId = JsonAsString(frames[frameIdx]["buildId"]); + std::string file = JsonAsString(frames[frameIdx]["file"]); + std::string offset = JsonAsString(frames[frameIdx]["offset"]); + std::string pc = JsonAsString(frames[frameIdx]["pc"]); + std::string symbol = JsonAsString(frames[frameIdx]["symbol"]); if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format, frameIdx, pc.c_str(), file.empty() ? "Unknown" : file.c_str()) <= 0) { return false; @@ -85,19 +93,30 @@ bool DfxJsonFormatter::FormatJsonStack(const std::string& jsonStack, std::string outStackStr.append("Failed to parse json stack info."); return false; } - + constexpr int maxThreadCount = 10000; + if (threads.size() > maxThreadCount) { + outStackStr.append("Thread count exceeds limit(10000)."); + return false; + } for (uint32_t i = 0; i < threads.size(); ++i) { std::string ss; Json::Value thread = threads[i]; if (thread["tid"].isConvertibleTo(Json::stringValue) && thread["thread_name"].isConvertibleTo(Json::stringValue)) { - ss += "Tid:" + thread["tid"].asString() + ", Name:" + thread["thread_name"].asString() + "\n"; + ss += "Tid:" + JsonAsString(thread["tid"]) + ", Name:" + JsonAsString(thread["thread_name"]) + "\n"; + } + if (!thread.isMember("frames") || !thread["frames"].isArray()) { + continue; } const Json::Value frames = thread["frames"]; + constexpr int maxFrameNum = 1000; + if (frames.size() > maxFrameNum) { + continue; + } for (uint32_t j = 0; j < frames.size(); ++j) { std::string frameStr = ""; bool formatStatus = false; - if (frames[j]["line"].asString().empty()) { + if (JsonAsString(frames[j]["line"]).empty()) { formatStatus = FormatNativeFrame(frames, j, frameStr); } else { formatStatus = FormatJsFrame(frames, j, frameStr); @@ -110,6 +129,7 @@ bool DfxJsonFormatter::FormatJsonStack(const std::string& jsonStack, std::string return false; } } + outStackStr.append(ss); } return true; diff --git a/interfaces/innerkits/signal_handler/BUILD.gn b/interfaces/innerkits/signal_handler/BUILD.gn index 28af9149b8522a9f3c15e045664b2752e6b010d6..48ca8f28ad61b3d4003dea0424d388285b0cd762 100644 --- a/interfaces/innerkits/signal_handler/BUILD.gn +++ b/interfaces/innerkits/signal_handler/BUILD.gn @@ -83,7 +83,7 @@ if (defined(ohos_lite)) { ] innerapi_tags = [ - "chipsetsdk_indirect", + "chipsetsdk_sp_indirect", "platformsdk_indirect", ] install_enable = true diff --git a/interfaces/innerkits/signal_handler/dfx_dumprequest.c b/interfaces/innerkits/signal_handler/dfx_dumprequest.c index be28a8955b2f5776b49738e025877d27e1967a4e..88e040a029d44307909ec8b97d4fc877795f5d63 100644 --- a/interfaces/innerkits/signal_handler/dfx_dumprequest.c +++ b/interfaces/innerkits/signal_handler/dfx_dumprequest.c @@ -395,16 +395,16 @@ static bool StartProcessdump(void) } else if (pid == 0) { if (!InitPipe()) { DFXLOGE("init pipe fail"); - _exit(errno); + syscall(SYS_exit, errno); } pid_t processDumpPid = ForkBySyscall(); if (processDumpPid < 0) { DFXLOGE("Failed to fork processdump(%{public}d)", errno); - _exit(errno); + syscall(SYS_exit, errno); } else if (processDumpPid > 0) { int ret = ReadProcessDumpGetRegsMsg() == true ? 0 : errno; DFXLOGI("exit the processdump parent process."); - _exit(ret); + syscall(SYS_exit, ret); } else { uint64_t endTime; int tid; @@ -422,7 +422,7 @@ static bool StartProcessdump(void) } else { DFXLOGI("current has spend all time, not execl processdump"); } - _exit(0); + syscall(SYS_exit, 0); } } return WaitProcessExitTimeout(pid, WAITPID_TIMEOUT); @@ -430,7 +430,7 @@ static bool StartProcessdump(void) static bool StartVMProcessUnwind(void) { - uint32_t startTime = GetAbsTimeMilliSecondsCInterce(); + uint64_t startTime = GetAbsTimeMilliSecondsCInterce(); pid_t pid = ForkBySyscall(); if (pid < 0) { DFXLOGE("Failed to fork vm process(%{public}d)", errno); @@ -443,10 +443,10 @@ static bool StartVMProcessUnwind(void) GetAbsTimeMilliSecondsCInterce() - startTime); g_vmRealPid = GetRealPid(); DFXLOGI("vm prorcecc read pid = %{public}ld", g_vmRealPid); - _exit(0); + syscall(SYS_exit, 0); } else { DFXLOGI("exit dummy vm process"); - _exit(0); + syscall(SYS_exit, 0); } } diff --git a/interfaces/innerkits/unwinder/BUILD.gn b/interfaces/innerkits/unwinder/BUILD.gn index fa4028c2ffb498b6825ee8809fabec4ba59478f3..12a6da598603fd2c4f42aa79512796214dc22164 100644 --- a/interfaces/innerkits/unwinder/BUILD.gn +++ b/interfaces/innerkits/unwinder/BUILD.gn @@ -333,6 +333,9 @@ if (defined(ohos_lite)) { "is_emulator=${is_emulator}", "DFX_NO_PRINT_LOG", ] + if (is_linux || is_mingw) { + defines += [ "is_host" ] + } } ohos_static_library("unwinder_host") { diff --git a/interfaces/innerkits/unwinder/src/unwind_local/thread_context.cpp b/interfaces/innerkits/unwinder/src/unwind_local/thread_context.cpp index 7895fa4f5e6f7ea608fef6cb5470f80a304190bd..b41bd3770aa6591e2f5cc1f1037eeb2502bf6d74 100644 --- a/interfaces/innerkits/unwinder/src/unwind_local/thread_context.cpp +++ b/interfaces/innerkits/unwinder/src/unwind_local/thread_context.cpp @@ -50,6 +50,9 @@ namespace { std::mutex g_localMutex; std::map> g_contextMap {}; constexpr std::chrono::seconds TIME_OUT = std::chrono::seconds(1); +#ifndef __aarch64__ +constexpr std::chrono::seconds TIME_OUT_IN_COPY_CONTEXT = std::chrono::seconds(3); +#endif void CreateContext(std::shared_ptr& threadContext) { @@ -175,7 +178,7 @@ NO_SANITIZE void CopyContextAndWaitTimeout(int sig, siginfo_t *si, void *context ctxPtr->tid = static_cast(ThreadContextStatus::CONTEXT_READY); ctxPtr->cv.notify_all(); - ctxPtr->cv.wait_for(lock, TIME_OUT); + ctxPtr->cv.wait_for(lock, TIME_OUT_IN_COPY_CONTEXT); ctxPtr->tid = static_cast(ThreadContextStatus::CONTEXT_UNUSED); #endif } diff --git a/services/BUILD.gn b/services/BUILD.gn index aa5b93dab08bea6e967d051be56feaa5b3217f7b..720a9d10b49b1b13a7b5614a092d4bd304acf462 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024 Huawei Device Co., Ltd. +# Copyright (c) 2021-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 @@ -20,7 +20,6 @@ faultloggerd_sources = [ "fault_logger_server.cpp", "fault_logger_service.cpp", "temp_file_manager.cpp", - "fault_coredump_service.cpp", "fault_common_util.cpp" ] @@ -78,6 +77,14 @@ if (defined(ohos_lite)) { } } else { faultloggerd_sources += [ + "./coredump/coredump_callback_service.cpp", + "./coredump/coredump_facade.cpp", + "./coredump/coredump_manager_service.cpp", + "./coredump/coredump_session_manager.cpp", + "./coredump/coredump_session_service.cpp", + "./coredump/coredump_session_state.cpp", + "./coredump/coredump_signal_service.cpp", + "./coredump/coredump_task_scheduler.cpp", "./snapshot/kernel_snapshot_content_builder.cpp", "./snapshot/kernel_snapshot_kernel_frame.cpp", "./snapshot/kernel_snapshot_manager.cpp", @@ -94,6 +101,7 @@ if (defined(ohos_lite)) { include_dirs = [ ".", + "./coredump", "./snapshot", "$faultloggerd_interfaces_path/common", "$faultloggerd_path/common/dfxlog", @@ -142,6 +150,12 @@ if (defined(ohos_lite)) { subsystem_name = "hiviewdfx" } + ohos_prebuilt_etc("fault_coredump.json") { + source = "config/fault_coredump.json" + part_name = "faultloggerd" + subsystem_name = "hiviewdfx" + } + ohos_executable("faultloggerd") { install_enable = true configs = [ @@ -156,13 +170,13 @@ if (defined(ohos_lite)) { "DFX_LOG_HILOG_BASE", "DFX_ENABLE_TRACE", ] - deps = [ ":faultlogger.conf", ":faultloggerd.para", ":faultloggerd.para.dac", ":faultloggerd_config.json", + ":fault_coredump.json", "$faultloggerd_frameworks_path/localhandler:dfx_local_handler_src", "$faultloggerd_interfaces_path/innerkits/procinfo:libdfx_procinfo", "$faultloggerd_path/common/dfxlog:dfx_hilog_base", diff --git a/services/config/fault_coredump.json b/services/config/fault_coredump.json new file mode 100644 index 0000000000000000000000000000000000000000..bc9ee7170456cb2c6e0c6f0a9d94a42bb274477f --- /dev/null +++ b/services/config/fault_coredump.json @@ -0,0 +1,34 @@ +{ + "whitelist": [0, 1202, 7005], + "coredumpProfiles": { + "FULL": { + "process": { + "prpsinfo": true, + "multiThread": true, + "auxv": true, + "dumpMappings": true + }, + "threads": { + "prstatus": true, + "fpregset": true, + "siginfo": true, + "dumpAll": true, + "armPacMask": true, + "armTaggedAddrCtrl": true + }, + "dumpType": "FULL", + "outputPath": "/data/storage/el2/base/files", + "maxCoredumpSize": 0, + "includeTags": true, + "hwsanTagRegion": 1048576, + "isPtraceBySelf": false, + "isNeedDumpPid": false, + "loadCfg": { + "coredumpFilter": 0, + "excludePaths": "[vvar]", + "requiredPriority": "r", + "excludeSubstrings": "CMGC" + } + } + } +} \ No newline at end of file diff --git a/services/coredump/coredump_callback_service.cpp b/services/coredump/coredump_callback_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7c5b6d2edcbdd2642d5aa8afb48a949a62c94cd --- /dev/null +++ b/services/coredump/coredump_callback_service.cpp @@ -0,0 +1,88 @@ +/* + * 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 "coredump_callback_service.h" +#include "faultloggerd_socket.h" + +namespace OHOS { +namespace HiviewDFX { +int32_t CoredumpCallbackService::OnRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpStatusData& requestData) +{ + DFXLOGI("Receive coredump status request for pid:%{public}d, status:%{public}d", requestData.pid, + requestData.coredumpStatus); + + int res = CoredumpCallbackValidator::ValidateRequest(socketName, connectionFd, requestData); + if (res != 0) { + SendMsgToSocket(connectionFd, &res, sizeof(res)); + return res; + } + + if (requestData.coredumpStatus == CoreDumpStatus::CORE_DUMP_START) { + res = HandleUpdateWorkerPid(requestData); + } else { + res = HandleReport(requestData); + } + SendMsgToSocket(connectionFd, &res, sizeof(res)); + return res; +} + +int32_t CoredumpCallbackService::HandleUpdateWorkerPid(const CoreDumpStatusData& requestData) +{ + if (requestData.processDumpPid <= 0) { + DFXLOGE("workpid is invalid, targetpid %{public}d errno%{public}d", requestData.pid, requestData.retCode); + } + + CoredumpCallbackReport req; + req.workerPid = requestData.processDumpPid; + bool ret = cf_.UpdateWorkerPid(requestData.pid, req.workerPid); + return ret ? ResponseCode::REQUEST_SUCCESS : ResponseCode::ABNORMAL_SERVICE; +} + +int32_t CoredumpCallbackService::HandleReport(const CoreDumpStatusData& requestData) +{ + CoredumpCallbackReport req; + req.status = requestData.retCode == 0 ? CoredumpStatus::SUCCESS : CoredumpStatus::FAILED; + req.filePath = requestData.fileName; + cf_.ReportResult(requestData.pid, req); + + return ResponseCode::REQUEST_SUCCESS; +} + +int32_t CoredumpCallbackValidator::ValidateRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpStatusData& requestData) +{ + if (!IsValidPid(requestData.pid)) { + DFXLOGE("Invalid PID: %{public}d", requestData.pid); + return ResponseCode::REQUEST_REJECT; + } + + if (!IsAuthorizedSocket(socketName)) { + DFXLOGE("Unauthorized socket: %{public}s", socketName.c_str()); + return ResponseCode::REQUEST_REJECT; + } + return 0; +} + +bool CoredumpCallbackValidator::IsValidPid(pid_t pid) +{ + return pid > 0; +} + +bool CoredumpCallbackValidator::IsAuthorizedSocket(const std::string& socketName) +{ + return socketName == SERVER_SOCKET_NAME; +} +} +} diff --git a/services/coredump/coredump_callback_service.h b/services/coredump/coredump_callback_service.h new file mode 100644 index 0000000000000000000000000000000000000000..340817fc59671d66843c84a055fa05120bc70bfb --- /dev/null +++ b/services/coredump/coredump_callback_service.h @@ -0,0 +1,44 @@ +/* + * 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 COREDUMP_CALLBACK_SERVICE_H +#define COREDUMP_CALLBACK_SERVICE_H + +#include "dfx_socket_request.h" +#include "fault_logger_service.h" +#include "coredump_facade.h" + +namespace OHOS { +namespace HiviewDFX { +class CoredumpCallbackService : public FaultLoggerService { +public: + int32_t OnRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpStatusData& requestData) override; +private: + int32_t HandleUpdateWorkerPid(const CoreDumpStatusData& requestData); + int32_t HandleReport(const CoreDumpStatusData& requestData); + CoredumpFacade cf_; +}; + +class CoredumpCallbackValidator { +public: + static int32_t ValidateRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpStatusData& requestData); +private: + static bool IsValidPid(pid_t pid); + static bool IsAuthorizedSocket(const std::string& socketName); +}; +} +} +#endif diff --git a/services/coredump/coredump_facade.cpp b/services/coredump/coredump_facade.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53dee5113f33f9bb53a4e079d88b303222678729 --- /dev/null +++ b/services/coredump/coredump_facade.cpp @@ -0,0 +1,76 @@ +/* + * 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 "coredump_facade.h" +#include "coredump_session_manager.h" + +namespace OHOS { +namespace HiviewDFX { +bool CoredumpFacade::CreateCoredump(const CreateCoredumpRequest& req) +{ + sessionService_.CreateSession(req); + signalService_.SendStartSignal(req.targetPid); + constexpr int32_t maxCoredumpDelayTime = 10 * 1000; + taskScheduler_.ScheduleCancelTime(req.targetPid, maxCoredumpDelayTime); + return true; +} + +void CoredumpFacade::CancelCoredump(SessionId sessionId) +{ + sessionService_.CancelSession(sessionId); + const auto session = CoredumpSessionManager::Instance().GetSession(sessionId); + if (!session) { + return; + } + stateContext_.HandleEvent(*session, CoredumpEvent::CANCEL); +} + +bool CoredumpFacade::UpdateWorkerPid(SessionId sessionId, pid_t workerPid) +{ + DFXLOGI("%{public}s sessionId %{public}d, workerPid %{public}d", __func__, sessionId, workerPid); + sessionService_.UpdateWorkerPid(sessionId, workerPid); + + const auto session = CoredumpSessionManager::Instance().GetSession(sessionId); + if (!session) { + return false; + } + stateContext_.HandleEvent(*session, CoredumpEvent::UPDATE_DUMPER); + return true; +} + +void CoredumpFacade::ReportResult(SessionId sessionId, const CoredumpCallbackReport& rpt) +{ + DFXLOGI("%{public}s sessionId %{public}d path %{public}s", __func__, sessionId, rpt.filePath.c_str()); + sessionService_.UpdateReport(sessionId, rpt); + const auto session = CoredumpSessionManager::Instance().GetSession(sessionId); + if (!session) { + return; + } + if (rpt.status == CoredumpStatus::SUCCESS) { + stateContext_.HandleEvent(*session, CoredumpEvent::REPORT_SUCCESS); + } else { + stateContext_.HandleEvent(*session, CoredumpEvent::REPORT_FAIL); + } +} + +void CoredumpFacade::OnTimeout(SessionId sessionId) +{ + const auto session = CoredumpSessionManager::Instance().GetSession(sessionId); + if (!session) { + return; + } + stateContext_.HandleEvent(*session, CoredumpEvent::TIMEOUT); +} +} +} diff --git a/services/coredump/coredump_facade.h b/services/coredump/coredump_facade.h new file mode 100644 index 0000000000000000000000000000000000000000..ba45e66f3b88f6244d4e5154e7452625a1832245 --- /dev/null +++ b/services/coredump/coredump_facade.h @@ -0,0 +1,40 @@ +/* + * 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 COREDUMP_FACADE_H +#define COREDUMP_FACADE_H + +#include "coredump_session_service.h" +#include "coredump_signal_service.h" +#include "coredump_task_scheduler.h" +#include "coredump_session_state.h" + +namespace OHOS { +namespace HiviewDFX { +class CoredumpFacade { +public: + bool CreateCoredump(const CreateCoredumpRequest& req); + void CancelCoredump(SessionId sessionId); + bool UpdateWorkerPid(SessionId sessionId, pid_t workerPid); + void ReportResult(SessionId sessionId, const CoredumpCallbackReport& rpt); + void OnTimeout(SessionId sessionId); +private: + CoredumpSessionService sessionService_; + CoredumpSignalService signalService_; + CoredumpTaskScheduler taskScheduler_; + SessionStateContext stateContext_; +}; +} +} +#endif diff --git a/services/coredump/coredump_manager_service.cpp b/services/coredump/coredump_manager_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87208c0e36a5d3ecb4b79d11af8db411780d9d34 --- /dev/null +++ b/services/coredump/coredump_manager_service.cpp @@ -0,0 +1,195 @@ +/* + * 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 "coredump_manager_service.h" + +#include +#include + +#include "coredump_model.h" +#include "fault_common_util.h" +#include "faultloggerd_socket.h" +#include "file_util.h" + +namespace OHOS { +namespace HiviewDFX { +int32_t CoredumpManagerService::OnRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpRequestData& requestData) +{ + DFXLOGI("Receive coredump request for pid:%{public}d, action:%{public}s.", requestData.pid, + requestData.coredumpAction == 0 ? "save":"cancel"); + + int res = CoredumpRequestValidator::ValidateRequest(socketName, connectionFd, requestData); + if (res != ResponseCode::REQUEST_SUCCESS) { + SendMsgToSocket(connectionFd, &res, sizeof(res)); + return res; + } + + if (requestData.coredumpAction == CoreDumpAction::DO_CORE_DUMP) { + res = HandleCreate(connectionFd, requestData); + } else if (requestData.coredumpAction == CoreDumpAction::CANCEL_CORE_DUMP) { + res = HandleCancel(requestData); + } + SendMsgToSocket(connectionFd, &res, sizeof(res)); + return res; +} + +int32_t CoredumpManagerService::HandleCreate(int32_t connectionFd, const CoreDumpRequestData& requestData) +{ + auto session = sessionManager_.GetSession(requestData.pid); + if (session) { + DFXLOGI("coredump pid %{public}d is dumping", requestData.pid); + return ResponseCode::CORE_DUMP_REPEAT; + } + + CreateCoredumpRequest request; + request.endTime = requestData.endTime; + request.clientFd = dup(connectionFd); + if (request.clientFd == -1) { + DFXLOGE("dup connection socket fd error %{public}d", errno); + return ResponseCode::DEFAULT_ERROR_CODE; + } + request.targetPid = requestData.pid; + return cf_.CreateCoredump(request) ? ResponseCode::REQUEST_SUCCESS : ResponseCode::DEFAULT_ERROR_CODE; +} + +int32_t CoredumpManagerService::HandleCancel(const CoreDumpRequestData& requestData) +{ + auto session = sessionManager_.GetSession(requestData.pid); + if (!session) { + DFXLOGI("pid %{public}d is not dumping, just return!", requestData.pid); + return ResponseCode::DEFAULT_ERROR_CODE; + } + + cf_.CancelCoredump(requestData.pid); + return ResponseCode::REQUEST_SUCCESS; +} + +bool CoredumpRequestValidator::CheckCoredumpUID(uint32_t callerUid) +{ + const std::string configPath = "/system/etc/fault_coredump.json"; + FaultCoredumpConfig::GetInstance(configPath); + + if (FaultCoredumpConfig::GetInstance().Contains(callerUid)) { + DFXLOGI("UID %{public}d is whitelisted.", callerUid); + return true; + } else { + DFXLOGI("UID %{public}d is NOT whitelisted.", callerUid); + return false; + } +} + +int32_t CoredumpRequestValidator::ValidateRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpRequestData& requestData) +{ + if (!IsValidPid(requestData.pid)) { + DFXLOGE("Invalid PID: %{public}d", requestData.pid); + return ResponseCode::REQUEST_REJECT; + } + + if (!IsAuthorizedSocket(socketName)) { + DFXLOGE("Unauthorized socket: %{public}s", socketName.c_str()); + return ResponseCode::REQUEST_REJECT; + } + + if (!IsAuthorizedUid(connectionFd)) { + DFXLOGE("Unauthorized UID:"); + return ResponseCode::REQUEST_REJECT; + } + + if (TempFileManager::CheckCrashFileRecord(requestData.pid)) { + DFXLOGW(" pid(%{public}d) has been crashed, break.", + requestData.pid); + return ResponseCode::CORE_PROCESS_CRASHED; + } + return ResponseCode::REQUEST_SUCCESS; +} + +bool CoredumpRequestValidator::IsValidPid(pid_t pid) +{ + return pid > 0; +} + +bool CoredumpRequestValidator::IsAuthorizedSocket(const std::string& socketName) +{ + return socketName == SERVER_SOCKET_NAME; +} + +bool CoredumpRequestValidator::IsAuthorizedUid(int32_t connectionFd) +{ + struct ucred creds; + if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd)) { + return false; + } + return CheckCoredumpUID(creds.uid); +} + +FaultCoredumpConfig& FaultCoredumpConfig::GetInstance(const std::string& jsonFilePath) +{ + static FaultCoredumpConfig instance; + static bool initialized = false; + + if (!initialized && !jsonFilePath.empty()) { + std::string jsonText; + if (!LoadStringFromFile(jsonFilePath, jsonText)) { + DFXLOGE("Failed to read JSON file."); + } else if (!instance.Parse(jsonText)) { + DFXLOGE("Failed to parse whitelist."); + } else { + initialized = true; + } + } + + return instance; +} + +bool FaultCoredumpConfig::Contains(uint32_t uid) const +{ + for (uint32_t allowed : uids) { + if (allowed == uid) return true; + } + return false; +} + +bool FaultCoredumpConfig::Parse(const std::string& jsonText) +{ + cJSON* root = cJSON_Parse(jsonText.c_str()); + if (!root) { + DFXLOGE("Failed to parse JSON: %{public}s", cJSON_GetErrorPtr()); + return false; + } + + const cJSON* whitelistArray = cJSON_GetObjectItem(root, "whitelist"); + if (!cJSON_IsArray(whitelistArray)) { + DFXLOGE("whitelist is missing or not an array"); + cJSON_Delete(root); + return false; + } + + cJSON* uid = nullptr; + cJSON_ArrayForEach(uid, whitelistArray) { + if (!cJSON_IsNumber(uid) || uid->valueint < 0) { + char *printed = cJSON_Print(uid); + DFXLOGE("Invalid UID in whitelist: %{public}s", printed); + cJSON_free(printed); + continue; + } + uids.push_back(static_cast(uid->valueint)); + } + + cJSON_Delete(root); + return true; +} +} +} diff --git a/services/coredump/coredump_manager_service.h b/services/coredump/coredump_manager_service.h new file mode 100644 index 0000000000000000000000000000000000000000..509823bb6898d2594afa21a0d1c3d9fff4df426c --- /dev/null +++ b/services/coredump/coredump_manager_service.h @@ -0,0 +1,63 @@ +/* + * 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 COREDUMP_MANAGER_SERVICE_H +#define COREDUMP_MANAGER_SERVICE_H + +#include "coredump_facade.h" +#include "dfx_socket_request.h" +#include "fault_logger_service.h" + +namespace OHOS { +namespace HiviewDFX { +class CoredumpManagerService : public FaultLoggerService { +public: + CoredumpManagerService(): sessionManager_(CoredumpSessionManager::Instance()) {} + int32_t OnRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpRequestData& requestData) override; +private: + int32_t HandleCreate(int32_t connectionFd, const CoreDumpRequestData& requestData); + int32_t HandleCancel(const CoreDumpRequestData& requestData); + CoredumpFacade cf_; + CoredumpSessionManager& sessionManager_; +}; + +class CoredumpRequestValidator { +public: + static int32_t ValidateRequest(const std::string& socketName, int32_t connectionFd, + const CoreDumpRequestData& requestData); +private: + static bool IsValidPid(pid_t pid); + static bool IsAuthorizedSocket(const std::string& socketName); + static bool IsAuthorizedUid(int32_t connectionFd); + static bool CheckCoredumpUID(uint32_t callerUid); +}; + +class FaultCoredumpConfig { +public: + static FaultCoredumpConfig& GetInstance(const std::string& jsonFilePath = ""); + + bool Contains(uint32_t uid) const; +private: + FaultCoredumpConfig() = default; + FaultCoredumpConfig(const FaultCoredumpConfig&) = delete; + FaultCoredumpConfig& operator=(const FaultCoredumpConfig&) = delete; + + bool Parse(const std::string& jsonText); + + std::vector uids; +}; +} +} +#endif diff --git a/services/coredump/coredump_model.h b/services/coredump/coredump_model.h new file mode 100644 index 0000000000000000000000000000000000000000..cb212a97b300ac150c6f37fbe0ced11eb0f827fe --- /dev/null +++ b/services/coredump/coredump_model.h @@ -0,0 +1,100 @@ +/* + * 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 COREDUMP_MODEL_H +#define COREDUMP_MODEL_H + +#include +#include +#include "dfx_log.h" + +namespace OHOS { +namespace HiviewDFX { +enum class CoredumpStatus { + PENDING, // 请求已接收,正在等待核心转储开始 + RUNNING, // 核心转储进行中 + SUCCESS, // 核心转储成功完成 + FAILED, // 核心转储失败 + CANCEL_PENDING, // 收到取消请求,正在等待取消执行 + CANCELED, // 已成功取消核心转储 + CANCEL_TIMEOUT, // 取消操作超时,核心转储未及时终止 + INVALID_STATUS +}; + +enum class CoredumpEvent { + UPDATE_DUMPER, // Worker 上报 PID + CANCEL, // 客户端发起取消 + REPORT_SUCCESS, // Worker 上报成功 + REPORT_FAIL, // Worker 上报失败 + TIMEOUT, // 超时未上报 + INVALID_EVENT +}; + +struct CreateCoredumpRequest { + pid_t targetPid; + std::string dumpType; + int clientFd; + uint64_t endTime; +}; + +struct CoredumpCallbackReport { + pid_t workerPid; + CoredumpStatus status; + std::string filePath; + int errorCode; +}; + +using SessionId = pid_t; +struct CoredumpSession { + SessionId sessionId {0}; + pid_t workerPid {0}; + bool cancelRequest {false}; + CoredumpStatus status {CoredumpStatus::PENDING}; + std::string filePath; + int errorCode {0}; + int clientFd {-1}; + uint64_t startTime {0}; + uint64_t endTime {0}; + int32_t timerFd {0}; + + std::string StatusToString(CoredumpStatus coredumpStatus) const + { + switch (coredumpStatus) { + case CoredumpStatus::PENDING: + return "PENDING"; + case CoredumpStatus::RUNNING: + return "RUNNING"; + case CoredumpStatus::SUCCESS: + return "SUCCESS"; + case CoredumpStatus::FAILED: + return "FAILED"; + case CoredumpStatus::CANCEL_PENDING: + return "CANCEL_PENDING"; + case CoredumpStatus::CANCELED: + return "CANCELED"; + case CoredumpStatus::CANCEL_TIMEOUT: + return "CANCEL_TIMEOUT"; + default: + return "UNKNOWN"; + } + } + + std::string ToString() const + { + return std::string("sessionId: ") + std::to_string(sessionId) + " " + StatusToString(status); + } +}; +} +} +#endif diff --git a/services/coredump/coredump_session_manager.cpp b/services/coredump/coredump_session_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15f9a23328edca49dc66400d17fdb2f07989c773 --- /dev/null +++ b/services/coredump/coredump_session_manager.cpp @@ -0,0 +1,67 @@ +/* + * 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 "coredump_session_manager.h" +#include "coredump_task_scheduler.h" +#include + +namespace OHOS { +namespace HiviewDFX { + +CoredumpSessionManager& CoredumpSessionManager::Instance() +{ + static CoredumpSessionManager sessionManager; + return sessionManager; +} + +SessionId CoredumpSessionManager::CreateSession(const CreateCoredumpRequest& request) +{ + CoredumpSession session; + session.sessionId = request.targetPid; + session.clientFd = request.clientFd; + session.status = CoredumpStatus::PENDING; + session.endTime = request.endTime; + + sessions_.emplace(session.sessionId, std::move(session)); + + DFXLOGI("success create session id %{public}d ", session.sessionId); + + return session.sessionId; +} + +CoredumpSession* CoredumpSessionManager::GetSession(SessionId sessionId) +{ + auto session = sessions_.find(sessionId); + if (session == sessions_.end()) { + DFXLOGW("fail to get sessin by id %{public}d", sessionId); + return nullptr; + } + return &session->second; +} + +void CoredumpSessionManager::RemoveSession(SessionId sessionId) +{ + if (auto it = sessions_.find(sessionId); it != sessions_.end()) { + DFXLOGI("success remove session %{public}d", sessionId); + if (int& fd = it->second.clientFd; fd >= 0) { + close(fd); + fd = -1; + } + + CoredumpTaskScheduler().CancelTimeout(sessionId); + sessions_.erase(it); + } +} +} +} diff --git a/services/coredump/coredump_session_manager.h b/services/coredump/coredump_session_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..195b0d5aba6353bc022fe3b30553b732907dc601 --- /dev/null +++ b/services/coredump/coredump_session_manager.h @@ -0,0 +1,39 @@ +/* + * 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 COREDUMP_SESSION_MANAGER_H +#define COREDUMP_SESSION_MANAGER_H + +#include + +#include "coredump_model.h" + +namespace OHOS { +namespace HiviewDFX { +class CoredumpSessionManager { +public: + static CoredumpSessionManager& Instance(); + SessionId CreateSession(const CreateCoredumpRequest& request); + CoredumpSession* GetSession(SessionId sessionId); + void RemoveSession(SessionId sessionId); + + CoredumpSessionManager(const CoredumpSessionManager&) = delete; + CoredumpSessionManager& operator =(const CoredumpSessionManager&) = delete; +private: + CoredumpSessionManager() = default; + std::unordered_map sessions_; +}; +} +} +#endif diff --git a/services/coredump/coredump_session_service.cpp b/services/coredump/coredump_session_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2974f03e4804b40e6610cecf4e4222fa82ca210c --- /dev/null +++ b/services/coredump/coredump_session_service.cpp @@ -0,0 +1,106 @@ +/* + * 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 "coredump_session_service.h" +#include "securec.h" +#include "faultloggerd_socket.h" + +namespace OHOS { +namespace HiviewDFX { +SessionId CoredumpSessionService::CreateSession(const CreateCoredumpRequest& request) +{ + return sessionManager_.CreateSession(request); +} + +bool CoredumpSessionService::CancelSession(SessionId sessionId) +{ + auto session = sessionManager_.GetSession(sessionId); + if (!session) { + return false; + } + session->cancelRequest = true; + return true; +} + +bool CoredumpSessionService::UpdateWorkerPid(SessionId sessionId, pid_t workerPid) +{ + auto session = sessionManager_.GetSession(sessionId); + if (!session) { + return false; + } + session->workerPid = workerPid; + return true; +} + +void CoredumpSessionService::UpdateReport(SessionId sessionId, const CoredumpCallbackReport& rpt) +{ + auto session = sessionManager_.GetSession(sessionId); + if (!session) { + return; + } + session->filePath = rpt.filePath; + session->errorCode = rpt.errorCode; +} + +int CoredumpSessionService::GetClientFd(SessionId sessionId) const +{ + auto session = sessionManager_.GetSession(sessionId); + if (!session) { + return -1; + } + return session->clientFd; +} + +bool CoredumpSessionService::WriteTimeoutAndClose(SessionId sessionId) +{ + CoreDumpResult coredumpRequst; + coredumpRequst.retCode = -1; + coredumpRequst.fileName[0] = '\0'; + return WriteResult(sessionId, coredumpRequst); +} + +bool CoredumpSessionService::WriteResultAndClose(SessionId sessionId) +{ + DFXLOGI("%{public}s sessionId %{public}d ", __func__, sessionId); + + auto session = sessionManager_.GetSession(sessionId); + if (!session) { + return false; + } + + CoreDumpResult coredumpResult; + if (strncpy_s(coredumpResult.fileName, sizeof(coredumpResult.fileName), + session->filePath.c_str(), session->filePath.size()) != 0) { + DFXLOGE("%{public}s :: strncpy failed.", __func__); + return false; + } + coredumpResult.retCode = session->errorCode; + + return WriteResult(sessionId, coredumpResult); +} + +bool CoredumpSessionService::WriteResult(SessionId sessionId, const CoreDumpResult& coredumpResult) +{ + auto session = sessionManager_.GetSession(sessionId); + if (!session) { + return false; + } + + int32_t savedConnectionFd = session->clientFd; + SendMsgToSocket(savedConnectionFd, &coredumpResult, sizeof(coredumpResult)); + sessionManager_.RemoveSession(sessionId); + return true; +} +} +} diff --git a/services/coredump/coredump_session_service.h b/services/coredump/coredump_session_service.h new file mode 100644 index 0000000000000000000000000000000000000000..fb862a3fd8abd375ab9935b2036be881f50809db --- /dev/null +++ b/services/coredump/coredump_session_service.h @@ -0,0 +1,43 @@ +/* + * 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 COREDUMP_SESSION_SERVICE_H +#define COREDUMP_SESSION_SERVICE_H + +#include "coredump_model.h" +#include "coredump_session_manager.h" +#include "dfx_socket_request.h" + +namespace OHOS { +namespace HiviewDFX { +class CoredumpSessionService { +public: + CoredumpSessionService():sessionManager_(CoredumpSessionManager::Instance()) {} + + SessionId CreateSession(const CreateCoredumpRequest& req); + bool CancelSession(SessionId sessionId); + bool UpdateWorkerPid(SessionId sessionId, pid_t workerPid); + void UpdateReport(SessionId sessionId, const CoredumpCallbackReport& rpt); + + int GetClientFd(SessionId sessionId) const; + + bool WriteTimeoutAndClose(SessionId sessionId); + bool WriteResultAndClose(SessionId sessionId); +private: + bool WriteResult(SessionId sessionId, const CoreDumpResult& result); + CoredumpSessionManager& sessionManager_; +}; +} +} +#endif diff --git a/services/coredump/coredump_session_state.cpp b/services/coredump/coredump_session_state.cpp new file mode 100644 index 0000000000000000000000000000000000000000..97a67e36c1d5a4cec95b66da3e6f653ad98a3a32 --- /dev/null +++ b/services/coredump/coredump_session_state.cpp @@ -0,0 +1,105 @@ +/* + * 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 "coredump_session_state.h" + +#include "dfx_log.h" + +namespace OHOS { +namespace HiviewDFX { + +std::unique_ptr SessionStateContext::CreateState(CoredumpStatus status) +{ + switch (status) { + case CoredumpStatus::PENDING: + return std::make_unique(); + case CoredumpStatus::RUNNING: + return std::make_unique(); + case CoredumpStatus::CANCEL_PENDING: + return std::make_unique(); + default: + return nullptr; + } +} + +void SessionStateContext::HandleEvent(CoredumpSession& session, CoredumpEvent event) +{ + auto stateHandler = CreateState(session.status); + if (!stateHandler) { + return; + } + stateHandler->OnEvent(event, session); +} + +void PendingState::OnEvent(CoredumpEvent event, CoredumpSession& session) +{ + switch (event) { + case CoredumpEvent::UPDATE_DUMPER: + session.status = CoredumpStatus::RUNNING; + break; + case CoredumpEvent::CANCEL: + session.cancelRequest = true; + session.status = CoredumpStatus::CANCEL_PENDING; + break; + case CoredumpEvent::TIMEOUT: + sessionService_.WriteTimeoutAndClose(session.sessionId); + session.status = CoredumpStatus::CANCEL_TIMEOUT; + break; + default: + DFXLOGW("pending state recevie invalid event"); + break; + } +} + +void RunningState::OnEvent(CoredumpEvent event, CoredumpSession& session) +{ + switch (event) { + case CoredumpEvent::REPORT_SUCCESS: + sessionService_.WriteResultAndClose(session.sessionId); + session.status = CoredumpStatus::SUCCESS; + break; + case CoredumpEvent::REPORT_FAIL: + sessionService_.WriteResultAndClose(session.sessionId); + session.status = CoredumpStatus::FAILED; + break; + case CoredumpEvent::CANCEL: + signalService_.SendCancelSignal(session.workerPid); + sessionService_.WriteResultAndClose(session.sessionId); + session.status = CoredumpStatus::CANCELED; + break; + default: + DFXLOGI("running state receive invalid event"); + break; + } +} + +void CancelPendingState::OnEvent(CoredumpEvent event, CoredumpSession& session) +{ + switch (event) { + case CoredumpEvent::UPDATE_DUMPER: + signalService_.SendCancelSignal(session.workerPid); + sessionService_.WriteResultAndClose(session.sessionId); + session.status = CoredumpStatus::CANCELED; + break; + case CoredumpEvent::TIMEOUT: + sessionService_.WriteTimeoutAndClose(session.sessionId); + session.status = CoredumpStatus::CANCEL_TIMEOUT; + break; + default: + DFXLOGI("cancel pending receive invalid event"); + break; + } +} +} +} \ No newline at end of file diff --git a/services/coredump/coredump_session_state.h b/services/coredump/coredump_session_state.h new file mode 100644 index 0000000000000000000000000000000000000000..5497a9aa773084e48d708d6f273b3478d00dfd17 --- /dev/null +++ b/services/coredump/coredump_session_state.h @@ -0,0 +1,63 @@ +/* + * 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 COREDUMP_SESSION_STATE_H +#define COREDUMP_SESSION_STATE_H + +#include "coredump_task_scheduler.h" +#include "coredump_signal_service.h" +#include "coredump_session_service.h" + +namespace OHOS { +namespace HiviewDFX { + +class SessionState; + +class SessionStateContext { +public: + void HandleEvent(CoredumpSession& session, CoredumpEvent event); + static std::unique_ptr CreateState(CoredumpStatus status); +}; + +class SessionState { +public: + virtual ~SessionState() = default; + virtual void OnEvent(CoredumpEvent event, CoredumpSession& session) = 0; +}; + +class PendingState : public SessionState { +public: + void OnEvent(CoredumpEvent event, CoredumpSession& session) override; +private: + CoredumpSessionService sessionService_; +}; + +class RunningState : public SessionState { +public: + void OnEvent(CoredumpEvent event, CoredumpSession& session) override; +private: + CoredumpSessionService sessionService_; + CoredumpSignalService signalService_; +}; + +class CancelPendingState : public SessionState { +public: + void OnEvent(CoredumpEvent event, CoredumpSession& session) override; +private: + CoredumpSessionService sessionService_; + CoredumpSignalService signalService_; +}; +} +} +#endif diff --git a/services/coredump/coredump_signal_service.cpp b/services/coredump/coredump_signal_service.cpp new file mode 100644 index 0000000000000000000000000000000000000000..534a9cb17d8adcbbe0c68834ab28d64658015edf --- /dev/null +++ b/services/coredump/coredump_signal_service.cpp @@ -0,0 +1,58 @@ +/* + * 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 "coredump_signal_service.h" + +#include + +#include "dfx_log.h" +#include "dfx_define.h" +#include "dfx_socket_request.h" +#include "faultloggerd_socket.h" +#include "proc_util.h" +#include "procinfo.h" +#include "fault_common_util.h" + +namespace OHOS { +namespace HiviewDFX { + +int32_t CoredumpSignalService::SendStartSignal(pid_t targetPid) +{ + siginfo_t si{0}; + si.si_signo = SIGLEAK_STACK; + si.si_errno = 0; + si.si_code = SIGLEAK_STACK_COREDUMP; + if (auto ret = FaultCommonUtil::SendSignalToProcess(targetPid, si); ret != ResponseCode::REQUEST_SUCCESS) { + return ret; + } + return ResponseCode::REQUEST_SUCCESS; +} + +int32_t CoredumpSignalService::SendCancelSignal(pid_t workerPid) +{ + siginfo_t si{0}; + si.si_signo = SIGTERM; + si.si_errno = 0; + si.si_code = SIGLEAK_STACK_COREDUMP; +#ifndef FAULTLOGGERD_TEST + if (syscall(SYS_rt_sigqueueinfo, workerPid, si.si_signo, &si) != 0) { + DFXLOGE("Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", + si.si_signo, errno); + return ResponseCode::CORE_DUMP_NOPROC; + } +#endif + return ResponseCode::REQUEST_SUCCESS; +} +} +} diff --git a/services/coredump/coredump_signal_service.h b/services/coredump/coredump_signal_service.h new file mode 100644 index 0000000000000000000000000000000000000000..fa71171b6d0f5a4ea2437e2010cf9fb3b412cb8b --- /dev/null +++ b/services/coredump/coredump_signal_service.h @@ -0,0 +1,29 @@ +/* + * 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 COREDUMP_SIGNAL_SERVICE_H +#define COREDUMP_SIGNAL_SERVICE_H + +#include + +namespace OHOS { +namespace HiviewDFX { +class CoredumpSignalService { +public: + int32_t SendStartSignal(pid_t targetPid); + int32_t SendCancelSignal(pid_t workerPid); +}; +} +} +#endif diff --git a/services/coredump/coredump_task_scheduler.cpp b/services/coredump/coredump_task_scheduler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87f38795dfaa885ca6c985e1f45c8b344886cf06 --- /dev/null +++ b/services/coredump/coredump_task_scheduler.cpp @@ -0,0 +1,59 @@ +/* + * 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 "coredump_task_scheduler.h" +#include "coredump_session_manager.h" +#include "dfx_util.h" +#include "epoll_manager.h" +#include "fault_logger_daemon.h" + +namespace OHOS { +namespace HiviewDFX { + +void CoredumpTaskScheduler::ScheduleCancelTime(SessionId sessionId, int timeoutMs) +{ + auto session = sessionManager_.GetSession(sessionId); + if (!session) { + return; + } + + auto endTime = session->endTime; + auto removeTask = [session]() { + CoredumpSessionManager::Instance().RemoveSession(session->sessionId); + DFXLOGI("timer real remove %{public}d", session->sessionId); + }; + + constexpr int32_t maxDelaySec = 60; // 60 : 60s + auto curTime = GetAbsTimeMilliSeconds(); + int32_t delaySec = endTime > curTime ? static_cast((endTime - curTime) / 1000) : 0; + delaySec = std::min(delaySec, maxDelaySec); + + auto delayTask = DelayTask::CreateInstance(removeTask, delaySec); + if (delayTask) { + session->timerFd = delayTask->GetFd(); + FaultLoggerDaemon::GetEpollManager(EpollManagerType::MAIN_SERVER).AddListener(std::move(delayTask)); + } +} + +void CoredumpTaskScheduler::CancelTimeout(SessionId sessionId) +{ + auto session = sessionManager_.GetSession(sessionId); + if (!session) { + return; + } + + FaultLoggerDaemon::GetEpollManager(EpollManagerType::MAIN_SERVER).RemoveListener(session->timerFd); +} +} +} diff --git a/services/coredump/coredump_task_scheduler.h b/services/coredump/coredump_task_scheduler.h new file mode 100644 index 0000000000000000000000000000000000000000..1fc3c3e05d250ada660aac73371f29870926374a --- /dev/null +++ b/services/coredump/coredump_task_scheduler.h @@ -0,0 +1,33 @@ +/* + * 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 COREDUMP_TASK_SCHEDULER_H +#define COREDUMP_TASK_SCHEDULER_H + +#include "coredump_model.h" +#include "coredump_session_manager.h" + +namespace OHOS { +namespace HiviewDFX { +class CoredumpTaskScheduler { +public: + CoredumpTaskScheduler() : sessionManager_(CoredumpSessionManager::Instance()) {} + void ScheduleCancelTime(SessionId sessionId, int timeoutMs); + void CancelTimeout(SessionId sessionId); +private: + CoredumpSessionManager& sessionManager_; +}; +} +} +#endif diff --git a/services/fault_common_util.cpp b/services/fault_common_util.cpp index e574434a3c0968fa0798fcf00fd771c10050404f..1d483d0d44b231981b87f2bc1f0716db9c9e965c 100644 --- a/services/fault_common_util.cpp +++ b/services/fault_common_util.cpp @@ -63,8 +63,8 @@ int32_t SendSignalToHapWatchdogThread(pid_t pid, const siginfo_t& si) } #ifndef FAULTLOGGERD_TEST if (syscall(SYS_rt_tgsigqueueinfo, pid, tid, si.si_signo, &si) != 0) { - DFXLOGE("%{public}s :: Failed to SYS_rt_tgsigqueueinfo signal(%{public}d), errno(%{public}d).", - FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); + DFXLOGE("Failed to SYS_rt_tgsigqueueinfo signal(%{public}d), errno(%{public}d).", + si.si_signo, errno); return ResponseCode::SDK_DUMP_NOPROC; } #endif @@ -79,8 +79,8 @@ int32_t SendSignalToProcess(pid_t pid, const siginfo_t& si) } #ifndef FAULTLOGGERD_TEST if (syscall(SYS_rt_sigqueueinfo, pid, si.si_signo, &si) != 0) { - DFXLOGE("%{public}s :: Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", - FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); + DFXLOGE("Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", + si.si_signo, errno); return ResponseCode::SDK_DUMP_NOPROC; } #endif @@ -88,4 +88,4 @@ int32_t SendSignalToProcess(pid_t pid, const siginfo_t& si) } } } -} \ No newline at end of file +} diff --git a/services/fault_common_util.h b/services/fault_common_util.h index bb1159b5a53f494e7138c1096ca761bb57c82963..33249f1f9288d69e4084f4c78e9c0eca2e5a838f 100644 --- a/services/fault_common_util.h +++ b/services/fault_common_util.h @@ -23,12 +23,10 @@ namespace OHOS { namespace HiviewDFX { namespace FaultCommonUtil { +bool GetUcredByPeerCred(struct ucred& rcred, int32_t connectionFd); int32_t SendSignalToHapWatchdogThread(pid_t pid, const siginfo_t& si); int32_t SendSignalToProcess(pid_t pid, const siginfo_t& si); - -bool GetUcredByPeerCred(struct ucred& rcred, int32_t connectionFd); } } } - -#endif \ No newline at end of file +#endif diff --git a/services/fault_coredump_service.cpp b/services/fault_coredump_service.cpp deleted file mode 100644 index 9e03dd84065496c2e1229b5c47e6e07972518c77..0000000000000000000000000000000000000000 --- a/services/fault_coredump_service.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/* - * 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 "fault_coredump_service.h" - -#include -#include -#include -#include -#include "dfx_define.h" -#include "dfx_log.h" -#include "dfx_trace.h" -#include "dfx_util.h" -#include "fault_logger_daemon.h" -#include "faultloggerd_socket.h" -#include "fault_common_util.h" -#include "procinfo.h" -#include "proc_util.h" -#include "string_printf.h" - -namespace OHOS { -namespace HiviewDFX { - -namespace { -constexpr const char* const FAULTLOGGERD_SERVICE_TAG = "FAULT_COREDUMP_SERVICE"; -bool CheckCoredumpUID(uint32_t callerUid) -{ - const uint32_t whitelist[] = { - 0, // rootUid - 1202, // dumpcatcherUid - 7005, // taskManagerUid - }; - if (std::find(std::begin(whitelist), std::end(whitelist), callerUid) == std::end(whitelist)) { - DFXLOGW("%{public}s :: CheckCoredumpUID :: Coredump Uid(%{public}d) is unexpectly.", - FAULTLOGGERD_SERVICE_TAG, callerUid); - return false; - } - return true; -} - -int32_t SendCancelSignal(int32_t processDumpPid) -{ - siginfo_t si{0}; - si.si_signo = SIGTERM; - si.si_errno = 0; - si.si_code = SIGLEAK_STACK_COREDUMP; -#ifndef FAULTLOGGERD_TEST - if (syscall(SYS_rt_sigqueueinfo, processDumpPid, si.si_signo, &si) != 0) { - DFXLOGE("%{public}s :: Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", - FAULTLOGGERD_SERVICE_TAG, si.si_signo, errno); - return ResponseCode::CORE_DUMP_NOPROC; - } -#endif - return ResponseCode::REQUEST_SUCCESS; -} - -bool SendMsgToCoredumpClient(int32_t targetPid, int32_t responseCode, const std::string& fileName, - RecorderProcessMap& coredumpRecorder) -{ - int32_t savedConnectionFd = -1; - - coredumpRecorder.GetCoredumpSocketId(targetPid, savedConnectionFd); - if (savedConnectionFd < 0) { - DFXLOGE("%{public}s :: Client sockFd has been crashed.", __func__); - return false; - } - - CoreDumpResult coredumpResult; - if (strncpy_s(coredumpResult.fileName, sizeof(coredumpResult.fileName), - fileName.c_str(), fileName.size()) != 0) { - DFXLOGE("%{public}s :: strncpy failed.", __func__); - return false; - } - coredumpResult.retCode = responseCode; - - if (SendMsgToSocket(savedConnectionFd, &coredumpResult, sizeof(coredumpResult))) { - return true; - } - return false; -} - -bool HandleCoredumpAndCleanup(int32_t targetPid, int32_t retCode, const std::string& fileName, - RecorderProcessMap& coredumpRecorder) -{ - if (!SendMsgToCoredumpClient(targetPid, retCode, fileName, coredumpRecorder)) { - DFXLOGE("Send message to client failed, %{public}s %{public}d", __func__, __LINE__); - } - - if (!coredumpRecorder.ClearTargetPid(targetPid)) { - DFXLOGE("Remove targetpid %{public}d failed, %{public}s %{public}d", targetPid, __func__, __LINE__); - return false; - } - return true; -} -} - -RecorderProcessMap& RecorderProcessMap::GetInstance() -{ - static RecorderProcessMap instance; - return instance; -} - -bool RecorderProcessMap::IsEmpty() -{ - return coredumpProcessMap.empty(); -} - -bool RecorderProcessMap::HasTargetPid(int32_t targetPid) -{ - return coredumpProcessMap.find(targetPid) != coredumpProcessMap.end(); -} - -void RecorderProcessMap::AddProcessMap(int32_t targetPid, const CoredumpProcessInfo& processInfo) -{ - coredumpProcessMap.emplace( - targetPid, - CoredumpProcessInfo(processInfo.processDumpPid, processInfo.coredumpSocketId, - processInfo.endTime, processInfo.cancelFlag) - ); -} - -bool RecorderProcessMap::ClearTargetPid(int32_t targetPid) -{ - auto it = coredumpProcessMap.find(targetPid); - if (it != coredumpProcessMap.end()) { - close(it->second.coredumpSocketId); - coredumpProcessMap.erase(it); - return true; - } - return false; -} - -bool RecorderProcessMap::SetCancelFlag(int32_t targetPid, bool flag) -{ - auto it = coredumpProcessMap.find(targetPid); - if (it != coredumpProcessMap.end()) { - it->second.cancelFlag = flag; - return true; - } - return false; -} - -bool RecorderProcessMap::SetProcessDumpPid(int32_t targetPid, int32_t processDumpPid) -{ - auto it = coredumpProcessMap.find(targetPid); - if (it != coredumpProcessMap.end()) { - it->second.processDumpPid = processDumpPid; - return true; - } - return false; -} - -bool RecorderProcessMap::GetCoredumpSocketId(int32_t targetPid, int32_t& coredumpSocketId) -{ - auto it = coredumpProcessMap.find(targetPid); - if (it != coredumpProcessMap.end()) { - coredumpSocketId = it->second.coredumpSocketId; - return true; - } - return false; -} - -bool RecorderProcessMap::GetProcessDumpPid(int32_t targetPid, int32_t& processDumpPid) -{ - auto it = coredumpProcessMap.find(targetPid); - if (it != coredumpProcessMap.end()) { - processDumpPid = it->second.processDumpPid; - return true; - } - return false; -} - -bool RecorderProcessMap::GetCancelFlag(int32_t targetPid, bool& flag) -{ - auto it = coredumpProcessMap.find(targetPid); - if (it != coredumpProcessMap.end()) { - flag = it->second.cancelFlag; - return true; - } - return false; -} - -#ifndef is_ohos_lite -bool CoredumpStatusService::HandleProcessDumpPid(int32_t targetPid, int32_t processDumpPid) -{ - if (processDumpPid <= 0 || targetPid <= 0) { - return false; - } - - if (!coredumpRecorder.HasTargetPid(targetPid)) { - return false; - } - - bool cancelFlag = false; - if (coredumpRecorder.GetCancelFlag(targetPid, cancelFlag)) { - if (!cancelFlag) { - coredumpRecorder.SetProcessDumpPid(targetPid, processDumpPid); - return true; - } - } - - if (SendCancelSignal(processDumpPid) != ResponseCode::REQUEST_SUCCESS) { - return false; - } - - int32_t retCode = ResponseCode::CORE_DUMP_CANCEL; - std::string fileName = ""; - HandleCoredumpAndCleanup(targetPid, retCode, fileName, coredumpRecorder); - return true; -} - -int32_t CoredumpStatusService::OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpStatusData& requestData) -{ - DFX_TRACE_SCOPED("CoredumpStatusServiceOnRequest"); - DFXLOGI("Receive coredump status request for pid:%{public}d, status:%{public}d", requestData.pid, - requestData.coredumpStatus); - - int32_t res = ResponseCode::REQUEST_SUCCESS; - if (requestData.coredumpStatus == CoreDumpStatus::CORE_DUMP_START) { - DFXLOGI("Processdump start %{public}s %{public}d", __func__, __LINE__); - int32_t processDumpPid = requestData.processDumpPid; - - if (!HandleProcessDumpPid(requestData.pid, processDumpPid)) { - DFXLOGE("Handle processDumpPid %{public}d failed", processDumpPid); - res = ResponseCode::ABNORMAL_SERVICE; - return res; - } - } else if (requestData.coredumpStatus == CoreDumpStatus::CORE_DUMP_END) { - DFXLOGI("Processdump finish %{public}s %{public}d", __func__, __LINE__); - - int32_t targetPid = requestData.pid; - char cfileName[256]; - if (strncpy_s(cfileName, sizeof(cfileName), requestData.fileName, sizeof(requestData.fileName)) != 0) { - DFXLOGE("%{public}s :: strncpy failed.", __func__); - return ResponseCode::DEFAULT_ERROR_CODE; - } - int32_t retCode = requestData.retCode; - HandleCoredumpAndCleanup(targetPid, retCode, cfileName, coredumpRecorder); - } - - SendMsgToSocket(connectionFd, &res, sizeof(res)); - return res; -} - -int32_t CoredumpService::Filter(const std::string& socketName, const CoreDumpRequestData& requestData, uint32_t uid) -{ - if (requestData.pid <= 0 || socketName != SERVER_SOCKET_NAME || !CheckCoredumpUID(uid)) { - DFXLOGE("%{public}s :: HandleCoreDumpRequest :: pid(%{public}d) or socketName(%{public}s) fail.", - FAULTLOGGERD_SERVICE_TAG, requestData.pid, socketName.c_str()); - return ResponseCode::REQUEST_REJECT; - } - if (TempFileManager::CheckCrashFileRecord(requestData.pid)) { - DFXLOGW("%{public}s :: pid(%{public}d) has been crashed, break.", - FAULTLOGGERD_SERVICE_TAG, requestData.pid); - return ResponseCode::CORE_PROCESS_CRASHED; - } - return ResponseCode::REQUEST_SUCCESS; -} - -int32_t CoredumpService::DoCoredumpRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpRequestData& requestData) -{ - struct ucred creds; - if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd)) { - DFXLOGE("Core dump pid(%{public}d) request failed to get cred.", requestData.pid); - return ResponseCode::REQUEST_REJECT; - } - int32_t responseCode = Filter(socketName, requestData, creds.uid); - if (responseCode != ResponseCode::REQUEST_SUCCESS) { - return responseCode; - } - - int32_t res = ResponseCode::REQUEST_SUCCESS; - int32_t coredumpSocketId = dup(connectionFd); - int32_t targetPid = requestData.pid; - if (coredumpRecorder.HasTargetPid(targetPid)) { - DFXLOGE("%{public}d is generating coredump, please do not repeat dump!", targetPid); - res = ResponseCode::CORE_DUMP_REPEAT; - SendMsgToSocket(coredumpSocketId, &res, sizeof(res)); - close(coredumpSocketId); - return res; - } - - siginfo_t si{0}; - si.si_signo = SIGLEAK_STACK; - si.si_errno = 0; - si.si_code = SIGLEAK_STACK_COREDUMP; - si.si_pid = static_cast(creds.pid); - if (auto ret = FaultCommonUtil::SendSignalToProcess(targetPid, si); ret != ResponseCode::REQUEST_SUCCESS) { - SendMsgToSocket(coredumpSocketId, &ret, sizeof(ret)); - close(coredumpSocketId); - return ret; - } - - int32_t processDumpPid = -1; - uint64_t endTime = requestData.endTime; - coredumpRecorder.AddProcessMap(targetPid, {processDumpPid, coredumpSocketId, endTime, false}); - SendMsgToSocket(coredumpSocketId, &res, sizeof(res)); - - auto removeTask = [targetPid, coredumpRecorderPtr = &coredumpRecorder]() { - coredumpRecorderPtr->ClearTargetPid(targetPid); - }; - - constexpr int32_t minDelays = 60; // 60 : 60s - int32_t delays = static_cast((endTime - GetAbsTimeMilliSeconds()) / 1000); - delays = std::min(delays, minDelays); - StartDelayTask(removeTask, delays); - return res; -} - -int32_t CoredumpService::CancelCoredumpRequest(int32_t connectionFd, const CoreDumpRequestData& requestData) -{ - int32_t targetPid = requestData.pid; - int32_t res = ResponseCode::REQUEST_SUCCESS; - if (!coredumpRecorder.HasTargetPid(targetPid)) { - DFXLOGE("No need to cancel!"); - res = ResponseCode::DEFAULT_ERROR_CODE; - SendMsgToSocket(connectionFd, &res, sizeof(res)); - return res; - } - - int32_t processDumpPid = -1; - if (coredumpRecorder.GetProcessDumpPid(targetPid, processDumpPid)) { - if (processDumpPid == -1) { - DFXLOGE("Can not get processdump pid!"); - coredumpRecorder.SetCancelFlag(targetPid, true); - } else { - DFXLOGI("processDumpPid get %{public}d %{public}d", processDumpPid, __LINE__); - - res = SendCancelSignal(processDumpPid); - if (res != ResponseCode::REQUEST_SUCCESS) { - return res; - } - int32_t retCode = ResponseCode::CORE_DUMP_CANCEL; - std::string fileName = ""; - HandleCoredumpAndCleanup(targetPid, retCode, fileName, coredumpRecorder); - } - } - - SendMsgToSocket(connectionFd, &res, sizeof(res)); - return res; -} - -int32_t CoredumpService::OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpRequestData& requestData) -{ - DFX_TRACE_SCOPED("CoredumpServiceOnRequest"); - DFXLOGI("Receive coredump request for pid:%{public}d, action:%{public}d.", requestData.pid, - requestData.coredumpAction); - - int32_t res = ResponseCode::REQUEST_SUCCESS; - if (requestData.coredumpAction == CoreDumpAction::DO_CORE_DUMP) { - DFXLOGI("Do coredump %{public}s %{public}d", __func__, __LINE__); - res = DoCoredumpRequest(socketName, connectionFd, requestData); - } else if (requestData.coredumpAction == CoreDumpAction::CANCEL_CORE_DUMP) { - DFXLOGI("Cancel coredump %{public}s %{public}d", __func__, __LINE__); - res = CancelCoredumpRequest(connectionFd, requestData); - } - return res; -} - -void CoredumpService::StartDelayTask(std::function workFunc, int32_t delayTime) -{ - auto delayTask = DelayTask::CreateInstance(workFunc, delayTime); - FaultLoggerDaemon::GetEpollManager(EpollManagerType::MAIN_SERVER).AddListener(std::move(delayTask)); -} -#endif -} -} \ No newline at end of file diff --git a/services/fault_coredump_service.h b/services/fault_coredump_service.h deleted file mode 100644 index 51180318d16e7ded607d1a63f370379aafb49e3a..0000000000000000000000000000000000000000 --- a/services/fault_coredump_service.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 FAULT_COREDUMP_SERVICE_H -#define FAULT_COREDUMP_SERVICE_H - -#include "csignal" -#include "cstdint" -#include "fault_logger_service.h" - -namespace OHOS { -namespace HiviewDFX { -struct CoredumpProcessInfo { - int32_t processDumpPid; - int32_t coredumpSocketId; - int endTime; - bool cancelFlag; - - CoredumpProcessInfo(int32_t processDump, int32_t connectionFd, int time, bool flag) - : processDumpPid(processDump), coredumpSocketId(connectionFd), endTime(time), cancelFlag(flag) {} -}; - -class RecorderProcessMap { -public: - RecorderProcessMap(const RecorderProcessMap&) = delete; - RecorderProcessMap& operator=(const RecorderProcessMap&) = delete; - - bool IsEmpty(); - bool HasTargetPid(int32_t targetPid); - void AddProcessMap(int32_t targetPid, const CoredumpProcessInfo& processInfo); - bool ClearTargetPid(int32_t targetPid); - bool GetCoredumpSocketId(int32_t targetPid, int32_t& coredumpSocketId); - bool GetCancelFlag(int32_t targetPid, bool& flag); - bool GetProcessDumpPid(int32_t targetPid, int32_t& processDumpPid); - bool SetCancelFlag(int32_t targetPid, bool flag); - bool SetProcessDumpPid(int32_t targetPid, int32_t processDumpPid); - static RecorderProcessMap& GetInstance(); - -private: - RecorderProcessMap() = default; - std::unordered_map coredumpProcessMap; -}; - -#ifndef is_ohos_lite -class CoredumpService : public FaultLoggerService { -public: - CoredumpService() : coredumpRecorder(RecorderProcessMap::GetInstance()) {} - int32_t OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpRequestData& requestData) override; - -private: - static int32_t Filter(const std::string& socketName, const CoreDumpRequestData& requestData, uint32_t uid); - void StartDelayTask(std::function workFunc, int32_t delayTime); - int32_t DoCoredumpRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpRequestData& requestData); - int32_t CancelCoredumpRequest(int32_t connectionFd, const CoreDumpRequestData& requestData); - RecorderProcessMap& coredumpRecorder; -}; - - -class CoredumpStatusService : public FaultLoggerService { -public: - CoredumpStatusService() : coredumpRecorder(RecorderProcessMap::GetInstance()) {} - int32_t OnRequest(const std::string& socketName, int32_t connectionFd, - const CoreDumpStatusData& requestData) override; - -private: - bool HandleProcessDumpPid(int32_t targetPid, int32_t processDumpPid); - RecorderProcessMap& coredumpRecorder; -}; -#endif -} -} - -#endif \ No newline at end of file diff --git a/services/fault_logger_server.cpp b/services/fault_logger_server.cpp index 618dfe81267502587a0b5d20876ddbdc443e6abf..7f60123108bce92e3bf8ea0b37af7ed873d4b11f 100644 --- a/services/fault_logger_server.cpp +++ b/services/fault_logger_server.cpp @@ -22,7 +22,10 @@ #include "dfx_define.h" #include "dfx_log.h" #include "faultloggerd_socket.h" -#include "fault_coredump_service.h" +#ifndef is_ohos_lite +#include "coredump_callback_service.h" +#include "coredump_manager_service.h" +#endif namespace OHOS { namespace HiviewDFX { @@ -47,8 +50,8 @@ bool SocketServer::Init() return false; } #ifndef is_ohos_lite - AddService(COREDUMP_CLIENT, std::make_unique()); - AddService(COREDUMP_PROCESS_DUMP_CLIENT, std::make_unique()); + AddService(COREDUMP_CLIENT, std::make_unique()); + AddService(COREDUMP_PROCESS_DUMP_CLIENT, std::make_unique()); AddService(PIPE_FD_CLIENT, std::make_unique()); AddService(SDK_DUMP_CLIENT, std::make_unique()); diff --git a/services/fault_logger_service.cpp b/services/fault_logger_service.cpp index 5f853165b0cd310889b0217ba39c1a14ac8960e6..1384a0af883a990f9af3204638c6f84a0c0e6f3e 100644 --- a/services/fault_logger_service.cpp +++ b/services/fault_logger_service.cpp @@ -332,7 +332,8 @@ int32_t SdkDumpService::OnRequest(const std::string& socketName, int32_t connect */ auto& faultLoggerPipe = FaultLoggerPipePair::CreateSdkDumpPipePair(requestData.pid, requestData.time); - if (auto ret = FaultCommonUtil::SendSignalToProcess(requestData.pid, si); ret != ResponseCode::REQUEST_SUCCESS) { + if (auto ret = FaultCommonUtil::SendSignalToProcess(requestData.pid, si); + ret != ResponseCode::REQUEST_SUCCESS) { FaultLoggerPipePair::DelSdkDumpPipePair(requestData.pid); return ret; } diff --git a/services/snapshot/i_kernel_snapshot_reporter.h b/services/snapshot/i_kernel_snapshot_reporter.h index 78efcca29238435f3d27e039685230a6cfa6f2e1..ab414283a61a1c5ebb8821495aada4f5f269f474 100644 --- a/services/snapshot/i_kernel_snapshot_reporter.h +++ b/services/snapshot/i_kernel_snapshot_reporter.h @@ -22,7 +22,7 @@ namespace OHOS { namespace HiviewDFX { class IKernelSnapshotReporter { public: - virtual void ReportEvents(std::vector& outputs) = 0; + virtual void ReportEvents(std::vector& outputs, const std::string& snapshot) = 0; virtual ~IKernelSnapshotReporter() = default; }; } // namespace HiviewDFX diff --git a/services/snapshot/kernel_snapshot_manager.cpp b/services/snapshot/kernel_snapshot_manager.cpp index 6b09d3ca39aa89129ab7408b5a4ff61e15e9ad5d..70828cc0fb4ff131f2b8b83bc9a5c75ffc68c39c 100644 --- a/services/snapshot/kernel_snapshot_manager.cpp +++ b/services/snapshot/kernel_snapshot_manager.cpp @@ -89,6 +89,9 @@ void KernelSnapshotManager::MonitorCrashKernelSnapshot() break; } std::string snapshotCont = ReadKernelSnapshot(); + if (snapshotCont.empty()) { + continue; + } processor->Process(snapshotCont); } } diff --git a/services/snapshot/kernel_snapshot_processor_impl.cpp b/services/snapshot/kernel_snapshot_processor_impl.cpp index e8b973c7b68038a5674b04e95d2c8324dd4f4bf3..c11de435050b72b6d50ae05a02d39398d6d91db5 100644 --- a/services/snapshot/kernel_snapshot_processor_impl.cpp +++ b/services/snapshot/kernel_snapshot_processor_impl.cpp @@ -37,7 +37,7 @@ void KernelSnapshotProcessorImpl::Process(const std::string& snapshot) DFXLOGE("reporter is null"); return; } - reporter_->ReportEvents(crashMaps); + reporter_->ReportEvents(crashMaps, snapshot); } } // namespace HiviewDFX } // namespace OHOS diff --git a/services/snapshot/kernel_snapshot_reporter.cpp b/services/snapshot/kernel_snapshot_reporter.cpp index c66195884aae2bd9e46209594e1ecd7215b5d57e..b16be5474001e25b18f7b1d33a5ca6177b7e110b 100644 --- a/services/snapshot/kernel_snapshot_reporter.cpp +++ b/services/snapshot/kernel_snapshot_reporter.cpp @@ -20,25 +20,28 @@ #include "dfx_log.h" #ifndef HISYSEVENT_DISABLE #include "hisysevent.h" +#include "hisysevent_c.h" #endif #include "kernel_snapshot_content_builder.h" +#include "dfx_util.h" namespace OHOS { namespace HiviewDFX { -void KernelSnapshotReporter::ReportEvents(std::vector& outputs) +void KernelSnapshotReporter::ReportEvents(std::vector& outputs, const std::string& snapshot) { for (auto& output : outputs) { + if (output[CrashSection::UID].empty()) { + DFXLOGE("msg format fail, report raw msg"); + ReportRawMsg(snapshot); + return; + } ReportCrashNoLogEvent(output); } } bool KernelSnapshotReporter::ReportCrashNoLogEvent(CrashMap& output) { - if (output[CrashSection::UID].empty()) { - DFXLOGE("uid is empty, not report"); - return false; - } #ifndef HISYSEVENT_DISABLE int32_t uid = static_cast(strtol(output[CrashSection::UID].c_str(), nullptr, DECIMAL_BASE)); int32_t pid = static_cast(strtol(output[CrashSection::PID].c_str(), nullptr, DECIMAL_BASE)); @@ -55,7 +58,50 @@ bool KernelSnapshotReporter::ReportCrashNoLogEvent(CrashMap& output) "PROCESS_NAME", output[CrashSection::PROCESS_NAME], "HAPPEN_TIME", timeStamp, "SUMMARY", KernelSnapshotContentBuilder(output).GenerateSummary()); - DFXLOGI("Report kernel snapshot event done, ret %{public}d", ret); + DFXLOGI("Report pid %{public}d kernel snapshot complate event ret %{public}d", pid, ret); + return ret == 0; +#else + DFXLOGI("Not supported for kernel snapshot report."); + return true; +#endif +} + +int32_t KernelSnapshotReporter::GetSnapshotPid(const std::string& content) +{ + std::string pidKey = "pid="; + auto pos = content.find(pidKey); + if (pos == std::string::npos) { + return 0; + } + auto end = content.find_first_of(')', pos); + if (end == std::string::npos) { + return 0; + } + pos += pidKey.size(); + std::string pidStr = content.substr(pos, end - pos); + auto pid = static_cast(strtol(pidStr.c_str(), nullptr, 10)); + if (errno == ERANGE) { + return 0; + } + return pid; +} + +bool KernelSnapshotReporter::ReportRawMsg(const std::string& content) +{ + if (content.empty()) { + return false; + } +#ifndef HISYSEVENT_DISABLE + int32_t pid = GetSnapshotPid(content); + char procName[] = "encrypt_snapshot_proc"; + HiSysEventParam params[] = { + {.name = "PID", .t = HISYSEVENT_UINT32, .v = { .ui32 = pid}, .arraySize = 0}, + {.name = "PROCESS_NAME", .t = HISYSEVENT_STRING, .v = {.s = procName}, .arraySize = 0}, + {.name = "HAPPEN_TIME", .t = HISYSEVENT_UINT64, .v = {.ui64 = GetTimeMilliSeconds()}, .arraySize = 0}, + }; + int ret = OH_HiSysEvent_Write("RELIABILITY", "CPP_CRASH_NO_LOG", + HISYSEVENT_FAULT, params, sizeof(params) / sizeof(params[0])); + DFXLOGI("Report pid %{public}d kernel snapshot raw event ret %{public}d", pid, ret); return ret == 0; #else DFXLOGI("Not supported for kernel snapshot report."); diff --git a/services/snapshot/kernel_snapshot_reporter.h b/services/snapshot/kernel_snapshot_reporter.h index c2422dea3c39ce52601cfa747cd748200303a637..70eb92f363a8ebfdb64d9b35ad07e218e39194ff 100644 --- a/services/snapshot/kernel_snapshot_reporter.h +++ b/services/snapshot/kernel_snapshot_reporter.h @@ -22,9 +22,11 @@ namespace OHOS { namespace HiviewDFX { class KernelSnapshotReporter : public IKernelSnapshotReporter { public: - void ReportEvents(std::vector& outputs) override; + void ReportEvents(std::vector& outputs, const std::string& snapshot) override; private: + bool ReportRawMsg(const std::string& content); bool ReportCrashNoLogEvent(CrashMap& output); + int32_t GetSnapshotPid(const std::string& content); }; } // namespace HiviewDFX } // namespace OHOS diff --git a/test/fuzztest/faultloggerdunwinder_fuzzer/faultloggerdunwinder_fuzzer.cpp b/test/fuzztest/faultloggerdunwinder_fuzzer/faultloggerdunwinder_fuzzer.cpp index 2836e8e4d1df296f2dc315e46979bf47a7df3c7e..51b52b6f5895381c11a6f20d67926eb9a21cd76b 100644 --- a/test/fuzztest/faultloggerdunwinder_fuzzer/faultloggerdunwinder_fuzzer.cpp +++ b/test/fuzztest/faultloggerdunwinder_fuzzer/faultloggerdunwinder_fuzzer.cpp @@ -28,7 +28,7 @@ namespace OHOS { namespace HiviewDFX { -const int FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH = 50; + struct TestArkFrameData { uintptr_t pc; uintptr_t fp; @@ -195,20 +195,21 @@ void TestThreadContext(const uint8_t* data, size_t size) void TestDfxInstrStatistic(const uint8_t* data, size_t size) { + constexpr int maxStringLength = 50; struct TestData { uint32_t type; uint64_t val; uint64_t errInfo; + char soName[maxStringLength]; }; if (data == nullptr || size < sizeof(TestData)) { return; } auto testData = reinterpret_cast(data); - std::string soName(reinterpret_cast(data), FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH); - data += FAULTLOGGER_FUZZTEST_MAX_STRING_LENGTH; InstrStatisticType statisticType = (testData->type % 10) ? InstructionEntriesArmExidx : UnsupportedArmExidx; DfxInstrStatistic& statistic = DfxInstrStatistic::GetInstance(); - statistic.SetCurrentStatLib(soName); + std::string testSoName(testData->soName, maxStringLength); + statistic.SetCurrentStatLib(testSoName); statistic.AddInstrStatistic(statisticType, testData->val, testData->errInfo); std::vector> result; statistic.DumpInstrStatResult(result); diff --git a/test/unittest/common/common_cutil_test.cpp b/test/unittest/common/common_cutil_test.cpp index ec0f7222844661a078967c0d4b5f53d262e69dd4..3c24122bfe1d70a1723645ffce86ec71463c6dfb 100644 --- a/test/unittest/common/common_cutil_test.cpp +++ b/test/unittest/common/common_cutil_test.cpp @@ -78,34 +78,6 @@ HWTEST_F(CommonCutilTest, DfxCutilTest003, TestSize.Level2) GTEST_LOG_(INFO) << "DfxCutilTest003: end."; } -/** - * @tc.name: DfxCutilTest004 - * @tc.desc: test cutil functions TrimAndDupStr - * @tc.type: FUNC - */ -HWTEST_F(CommonCutilTest, DfxCutilTest004, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "DfxCutilTest004: start."; - ASSERT_FALSE(TrimAndDupStr(nullptr, nullptr)); - GTEST_LOG_(INFO) << "DfxCutilTest004: end."; -} - -/** - * @tc.name: DfxCutilTest005 - * @tc.desc: test cutil functions TrimAndDupStr - * @tc.type: FUNC - */ -HWTEST_F(CommonCutilTest, DfxCutilTest005, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "DfxCutilTest005: start."; - const char src[] = "ab cd \n ef"; - char dst[11] = {0}; // 11: The length is consistent with the src[] array - ASSERT_TRUE(TrimAndDupStr(src, dst)); - GTEST_LOG_(INFO) << "dst:" << dst; - ASSERT_EQ(strncmp(dst, "abcd", 5), 0); // 5:length of "abcd" - GTEST_LOG_(INFO) << "DfxCutilTest005: end."; -} - /** * @tc.name: TraceTest001 * @tc.desc: test Trace functions DfxStartTraceDlsym diff --git a/test/unittest/common/common_test.cpp b/test/unittest/common/common_test.cpp index 2a8a8cf7dd1ba1d9ffb7997aa2a2ce862bddcd8d..d473028d89fdacc471eb3185633c19fd8f7400df 100644 --- a/test/unittest/common/common_test.cpp +++ b/test/unittest/common/common_test.cpp @@ -46,8 +46,8 @@ static void getLibPathsBySystemBits(vector &filePaths) "/system/lib64/libstacktrace_rust.dylib.so", "/system/lib64/libpanic_handler.dylib.so", "/system/lib64/platformsdk/libjson_stack_formatter.z.so", - "/system/lib64/chipset-sdk/libdfx_signalhandler.z.so", "/system/lib64/chipset-sdk/libcrash_exception.z.so", + "/system/lib64/chipset-sdk-sp/libdfx_signalhandler.z.so", "/system/lib64/chipset-sdk-sp/librustc_demangle.z.so", "/system/lib64/chipset-sdk-sp/libasync_stack.z.so", "/system/lib64/chipset-sdk-sp/libdfx_dumpcatcher.z.so", @@ -61,8 +61,8 @@ static void getLibPathsBySystemBits(vector &filePaths) "/system/lib/libstacktrace_rust.dylib.so", "/system/lib/libpanic_handler.dylib.so", "/system/lib/platformsdk/libjson_stack_formatter.z.so", - "/system/lib/chipset-sdk/libdfx_signalhandler.z.so", "/system/lib/chipset-sdk/libcrash_exception.z.so", + "/system/lib/chipset-sdk-sp/libdfx_signalhandler.z.so", "/system/lib/chipset-sdk-sp/librustc_demangle.z.so", "/system/lib/chipset-sdk-sp/libasync_stack.z.so", "/system/lib/chipset-sdk-sp/libdfx_dumpcatcher.z.so", diff --git a/test/unittest/faultloggerd/BUILD.gn b/test/unittest/faultloggerd/BUILD.gn index 4538769eb57e2c0d32c9ce52e983831cba504c4d..93904c827dbc540b653574767c2c062e91a0d059 100644 --- a/test/unittest/faultloggerd/BUILD.gn +++ b/test/unittest/faultloggerd/BUILD.gn @@ -64,7 +64,6 @@ if (defined(ohos_lite)) { "$faultloggerd_path/services/fault_logger_service.cpp", "$faultloggerd_path/services/temp_file_manager.cpp", "$faultloggerd_path/services/fault_common_util.cpp", - "$faultloggerd_path/services/fault_coredump_service.cpp", "faultlogger_server_test.cpp", "faultloggerd_test.cpp", "temp_file_manager_test.cpp", @@ -116,12 +115,14 @@ if (defined(ohos_lite)) { "$faultloggerd_interfaces_path/innerkits/procinfo/include", "$faultloggerd_path/services", "$faultloggerd_path/test/utils", + "$faultloggerd_path/services/coredump", ] sources = [ "$faultloggerd_path/interfaces/innerkits/faultloggerd_client/faultloggerd_client.cpp", "$faultloggerd_path/interfaces/innerkits/faultloggerd_client/faultloggerd_socket.cpp", "faultlogger_server_test.cpp", "faultloggerd_client_test.cpp", + "faultloggerd_coredump_test.cpp", "faultloggerd_test.cpp", "temp_file_manager_test.cpp", ] diff --git a/test/unittest/faultloggerd/faultloggerd_client_test.cpp b/test/unittest/faultloggerd/faultloggerd_client_test.cpp index 2a832cbb306157afde1bf48f59513976c0d5d5a1..f07109bbc289d6f7ea6ed6c3cea52beda521e425 100644 --- a/test/unittest/faultloggerd/faultloggerd_client_test.cpp +++ b/test/unittest/faultloggerd/faultloggerd_client_test.cpp @@ -30,7 +30,6 @@ #include "dfx_util.h" #include "faultloggerd_client.h" #include "fault_common_util.h" -#include "fault_coredump_service.h" #include "faultloggerd_test.h" #include "fault_logger_daemon.h" #include "smart_fd.h" @@ -58,34 +57,6 @@ void FaultloggerdClientTest::SetUpTestCase() std::this_thread::sleep_for(std::chrono::milliseconds(waitTime)); } -/** - * @tc.name: SendSignalToHapWatchdogThreadTest - * @tc.desc: Test send signal to watchdog thread - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, SendSignalToHapWatchdogThreadTest, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "SendSignalToHapWatchdogThreadTest: start."; - pid_t pid = -1; - siginfo_t si = {}; - ASSERT_EQ(FaultCommonUtil::SendSignalToHapWatchdogThread(pid, si), ResponseCode::DEFAULT_ERROR_CODE); - GTEST_LOG_(INFO) << "SendSignalToHapWatchdogThreadTest: end."; -} - -/** - * @tc.name: SendSignalToProcessTest - * @tc.desc: SendSignalToProcess - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, SendSignalToProcessTest, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "SendSignalToProcessTest: start."; - pid_t pid = -1; - siginfo_t si = {}; - ASSERT_EQ(FaultCommonUtil::SendSignalToProcess(pid, si), ResponseCode::REQUEST_SUCCESS); - GTEST_LOG_(INFO) << "SendSignalToProcessTest: end."; -} - /** * @tc.name: GetUcredByPeerCredTest * @tc.desc: GetUcredByPeerCred @@ -101,210 +72,6 @@ HWTEST_F(FaultloggerdClientTest, GetUcredByPeerCredTest, TestSize.Level2) GTEST_LOG_(INFO) << "GetUcredByPeerCredTest: end."; } -/** - * @tc.name: HandleProcessDumpPidTest001 - * @tc.desc: HandleProcessDumpPid - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, HandleProcessDumpPidTest001, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "HandleProcessDumpPidTest001: start."; - int32_t targetPid = 123; - int32_t processDumpPid = -1; - CoredumpStatusService coredumpStatusService; - EXPECT_FALSE(coredumpStatusService.HandleProcessDumpPid(targetPid, processDumpPid)); - - GTEST_LOG_(INFO) << "HandleProcessDumpPidTest001: end."; -} - -/** - * @tc.name: HandleProcessDumpPidTest002 - * @tc.desc: HandleProcessDumpPid - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, HandleProcessDumpPidTest002, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "HandleProcessDumpPidTest002: start."; - int32_t targetPid = 123; - int32_t processDumpPid = 456; - CoredumpStatusService coredumpStatusService; - EXPECT_FALSE(coredumpStatusService.HandleProcessDumpPid(targetPid, processDumpPid)); - GTEST_LOG_(INFO) << "HandleProcessDumpPidTest002: end."; -} - -/** - * @tc.name: DoCoredumpRequestTest - * @tc.desc: DoCoredumpRequest - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, DoCoredumpRequestTest, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "DoCoredumpRequestTest: start."; - std::string socketName = "test_socket"; - int32_t connectionFd = 1; - CoreDumpRequestData requestData = {}; - CoredumpService coredumpService; - ASSERT_EQ(coredumpService.DoCoredumpRequest(socketName, connectionFd, requestData), ResponseCode::REQUEST_REJECT); - GTEST_LOG_(INFO) << "DoCoredumpRequestTest: end."; -} - -/** - * @tc.name: RecorderProcessMapTest - * @tc.desc: RecorderProcessMap - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, RecorderProcessMapTest, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "RecorderProcessMapTest: start."; - RecorderProcessMap recorderProcessMap; - int32_t coredumpSocketId = 0; - int32_t processDumpPid = getpid(); - bool flag = false; - EXPECT_FALSE(recorderProcessMap.ClearTargetPid(getpid())); - EXPECT_FALSE(recorderProcessMap.SetCancelFlag(getpid(), true)); - EXPECT_FALSE(recorderProcessMap.SetProcessDumpPid(getpid(), getpid())); - EXPECT_FALSE(recorderProcessMap.GetCoredumpSocketId(getpid(), coredumpSocketId)); - EXPECT_FALSE(recorderProcessMap.GetProcessDumpPid(getpid(), processDumpPid)); - EXPECT_FALSE(recorderProcessMap.GetCancelFlag(getpid(), flag)); - GTEST_LOG_(INFO) << "RecorderProcessMapTest: end."; -} - -/** - * @tc.name: CoreDumpCbTest001 - * @tc.desc: Test startcoredumpcb and finishcoredumpcb process - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest001, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest001: start."; - int32_t retCode = ResponseCode::REQUEST_SUCCESS; - std::string fileName = "com.ohos.sceneboard.dmp"; - ASSERT_EQ(StartCoredumpCb(getpid(), getpid()), ResponseCode::ABNORMAL_SERVICE); - ASSERT_EQ(FinishCoredumpCb(getpid(), fileName, retCode), ResponseCode::REQUEST_SUCCESS); - GTEST_LOG_(INFO) << "CoreDumpCbTest001: end."; -} - -/** - * @tc.name: CoreDumpCbTest002 - * @tc.desc: Test coredump process - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest002, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest002: start."; - int32_t retCode = ResponseCode::REQUEST_SUCCESS; - std::string fileName = "com.ohos.sceneboard.dmp"; - - auto threadFunc = [&fileName, retCode]() { - sleep(1); - StartCoredumpCb(getpid(), getpid()); - FinishCoredumpCb(getpid(), fileName, retCode); - }; - - std::thread t(threadFunc); - t.detach(); - auto ret = SaveCoredumpToFileTimeout(getpid()); - ASSERT_EQ(ret, "com.ohos.sceneboard.dmp"); - GTEST_LOG_(INFO) << "CoreDumpCbTest002: end."; -} - -/** - * @tc.name: CoreDumpCbTest003 - * @tc.desc: Test coredump cancel process - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest003, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest003: start."; - auto threadFunc = []() { - sleep(1); - ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::REQUEST_SUCCESS); - StartCoredumpCb(getpid(), getpid()); // to clean processmap - }; - - std::thread t(threadFunc); - t.detach(); - auto ret = SaveCoredumpToFileTimeout(getpid()); - ASSERT_EQ(ret, ""); - GTEST_LOG_(INFO) << "CoreDumpCbTest003: end."; -} - -/** - * @tc.name: CoreDumpCbTest004 - * @tc.desc: Test coredump cancel process - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest004, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest004: start."; - auto threadFunc = []() { - sleep(1); - StartCoredumpCb(getpid(), getpid()); - ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::REQUEST_SUCCESS); - }; - - std::thread t(threadFunc); - t.detach(); - auto ret = SaveCoredumpToFileTimeout(getpid()); - ASSERT_EQ(ret, ""); - GTEST_LOG_(INFO) << "CoreDumpCbTest004: end."; -} - -/** - * @tc.name: CoreDumpCbTest005 - * @tc.desc: Test coredump cancel process - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest005, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest005: start."; - ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::DEFAULT_ERROR_CODE); - GTEST_LOG_(INFO) << "CoreDumpCbTest005: end."; -} - -/** - * @tc.name: CoreDumpCbTest006 - * @tc.desc: Test coredump repeat process - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest006, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest006: start."; - int32_t retCode = ResponseCode::REQUEST_SUCCESS; - std::string fileName = "com.ohos.sceneboard.dmp"; - - auto threadFunc = [&fileName, retCode]() { - sleep(1); - ASSERT_EQ(SaveCoredumpToFileTimeout(getpid()), ""); - StartCoredumpCb(getpid(), getpid()); - FinishCoredumpCb(getpid(), fileName, retCode); - }; - - std::thread t(threadFunc); - t.detach(); - auto ret = SaveCoredumpToFileTimeout(getpid()); - ASSERT_EQ(ret, "com.ohos.sceneboard.dmp"); - GTEST_LOG_(INFO) << "CoreDumpCbTest006: end."; -} - -/** - * @tc.name: CoreDumpCbTest007 - * @tc.desc: Test coredump process when targetPid = -1 - * @tc.type: FUNC - */ -HWTEST_F(FaultloggerdClientTest, CoreDumpCbTest007, TestSize.Level2) -{ - GTEST_LOG_(INFO) << "CoreDumpCbTest007: start."; - int32_t targetPid = -1; - int32_t retCode = ResponseCode::REQUEST_SUCCESS; - std::string fileName = "com.ohos.sceneboard.dmp"; - ASSERT_EQ(SaveCoredumpToFileTimeout(targetPid), ""); - ASSERT_EQ(CancelCoredump(targetPid), ResponseCode::DEFAULT_ERROR_CODE); - ASSERT_EQ(StartCoredumpCb(targetPid, getpid()), ResponseCode::DEFAULT_ERROR_CODE); - ASSERT_EQ(FinishCoredumpCb(targetPid, fileName, retCode), ResponseCode::DEFAULT_ERROR_CODE); - GTEST_LOG_(INFO) << "CoreDumpCbTest007: end."; -} - /** * @tc.name: RequestSdkDumpTest001 * @tc.desc: test the function for RequestSdkDump. diff --git a/test/unittest/faultloggerd/faultloggerd_coredump_test.cpp b/test/unittest/faultloggerd/faultloggerd_coredump_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4ce3458063401abb3716ef5c2878bfc0854fec10 --- /dev/null +++ b/test/unittest/faultloggerd/faultloggerd_coredump_test.cpp @@ -0,0 +1,596 @@ +/* + * 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 +#include +#include + +#if defined(HAS_LIB_SELINUX) +#include +#endif + +#include +#include +#include +#include +#include "dfx_test_util.h" +#include "dfx_util.h" +#include "faultloggerd_client.h" +#include "fault_common_util.h" +#include "coredump_manager_service.h" +#include "faultloggerd_test.h" +#include "fault_logger_daemon.h" +#include "smart_fd.h" +#include "coredump_callback_service.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +namespace HiviewDFX { +class FaultloggerdCoredumpTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); +}; + +void FaultloggerdCoredumpTest::TearDownTestCase() +{ +} + +void FaultloggerdCoredumpTest::SetUpTestCase() +{ + FaultLoggerdTestServer::GetInstance(); + constexpr int waitTime = 1500; // 1.5s; + std::this_thread::sleep_for(std::chrono::milliseconds(waitTime)); +} + +/** + * @tc.name: SendSignalToHapWatchdogThreadTest + * @tc.desc: Test send signal to watchdog thread + * @tc.type: FUNC + */ + HWTEST_F(FaultloggerdCoredumpTest, SendSignalToHapWatchdogThreadTest, TestSize.Level2) + { + GTEST_LOG_(INFO) << "SendSignalToHapWatchdogThreadTest: start."; + pid_t pid = -1; + siginfo_t si = {}; + EXPECT_EQ(FaultCommonUtil::SendSignalToHapWatchdogThread(pid, si), ResponseCode::DEFAULT_ERROR_CODE); + + pid = GetProcessPid("com.ohos.sceneboard"); + FaultCommonUtil::SendSignalToHapWatchdogThread(pid, si); + + GTEST_LOG_(INFO) << "SendSignalToHapWatchdogThreadTest: end."; +} + +/** + * @tc.name: SendSignalToProcessTest + * @tc.desc: SendSignalToProcess + * @tc.type: FUNC + */ + HWTEST_F(FaultloggerdCoredumpTest, SendSignalToProcessTest, TestSize.Level2) + { + GTEST_LOG_(INFO) << "SendSignalToProcessTest: start."; + pid_t pid = -1; + siginfo_t si = {}; + EXPECT_EQ(FaultCommonUtil::SendSignalToProcess(pid, si), ResponseCode::REQUEST_SUCCESS); + pid = GetProcessPid("com.ohos.sceneboard"); + EXPECT_EQ(FaultCommonUtil::SendSignalToProcess(pid, si), ResponseCode::REQUEST_SUCCESS); + GTEST_LOG_(INFO) << "SendSignalToProcessTest: end."; +} + +/** + * @tc.name: SendStartSignal + * @tc.desc: SendSignalToProcess + * @tc.type: FUNC + */ + HWTEST_F(FaultloggerdCoredumpTest, SendStartSignal, TestSize.Level2) + { + GTEST_LOG_(INFO) << "SendStartSignal: start."; + pid_t pid = -1; + siginfo_t si = {}; + CoredumpSignalService().SendStartSignal(pid); + GTEST_LOG_(INFO) << "SendStartSignal: end."; +} + +/** + * @tc.name: GetUcredByPeerCredTest + * @tc.desc: GetUcredByPeerCred + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, GetUcredByPeerCredTest, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "GetUcredByPeerCredTest: start."; + int32_t connectionFd = 0; + struct ucred rcred; + bool result = FaultCommonUtil::GetUcredByPeerCred(rcred, connectionFd); + EXPECT_FALSE(result); + GTEST_LOG_(INFO) << "GetUcredByPeerCredTest: end."; +} + +/** + * @tc.name: HandleProcessDumpPidTest001 + * @tc.desc: HandleProcessDumpPid + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, HandleProcessDumpPidTest001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "HandleProcessDumpPidTest001: start."; + int32_t targetPid = 123; + int32_t processDumpPid = -1; + + CoreDumpStatusData data; + CoredumpCallbackService coredumpStatusService; + coredumpStatusService.HandleUpdateWorkerPid(data); + + GTEST_LOG_(INFO) << "HandleProcessDumpPidTest001: end."; +} + +/** + * @tc.name: HandleProcessDumpPidTest002 + * @tc.desc: HandleProcessDumpPid + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, HandleProcessDumpPidTest002, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "HandleProcessDumpPidTest002: start."; + int32_t targetPid = 123; + int32_t processDumpPid = 456; + + CoreDumpStatusData data; + CoredumpCallbackService coredumpStatusService; + coredumpStatusService.HandleUpdateWorkerPid(data); + + auto ret = coredumpStatusService.OnRequest("", -1, data); + EXPECT_EQ(ret, ResponseCode::REQUEST_REJECT); + GTEST_LOG_(INFO) << "HandleProcessDumpPidTest002: end."; +} + +/** + * @tc.name: DoCoredumpRequestTest + * @tc.desc: DoCoredumpRequest + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, DoCoredumpRequestTest, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "DoCoredumpRequestTest: start."; + std::string socketName = "test_socket"; + int32_t connectionFd = 1; + CoreDumpRequestData requestData = { + .pid = 666 + }; + CoredumpManagerService coredumpService; + auto ret = coredumpService.HandleCreate(connectionFd, requestData); + coredumpService.HandleCancel(requestData); + requestData.pid = 999; + coredumpService.HandleCancel(requestData); + + GTEST_LOG_(INFO) << "DoCoredumpRequestTest: end."; +} + +/** + * @tc.name: RecorderProcessMapTest + * @tc.desc: test sessionManager + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, RecorderProcessMapTest, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "RecorderProcessMapTest: start."; + auto& sessionManager = CoredumpSessionManager::Instance(); + sessionManager.RemoveSession(0); + GTEST_LOG_(INFO) << "RecorderProcessMapTest: end."; +} + +/** + * @tc.name: CoreDumpCbTest001 + * @tc.desc: Test startcoredumpcb and finishcoredumpcb process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoreDumpCbTest001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest001: start."; + int32_t retCode = ResponseCode::REQUEST_SUCCESS; + std::string fileName = "com.ohos.sceneboard.dmp"; + ASSERT_EQ(StartCoredumpCb(getpid(), getpid()), ResponseCode::ABNORMAL_SERVICE); + ASSERT_EQ(FinishCoredumpCb(getpid(), fileName, retCode), ResponseCode::REQUEST_SUCCESS); + GTEST_LOG_(INFO) << "CoreDumpCbTest001: end."; +} + +/** + * @tc.name: CoreDumpCbTest002 + * @tc.desc: Test coredump process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoreDumpCbTest002, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest002: start."; + int32_t retCode = ResponseCode::REQUEST_SUCCESS; + std::string fileName = "com.ohos.sceneboard.dmp"; + + auto threadFunc = [&fileName, retCode]() { + sleep(1); + StartCoredumpCb(getpid(), getpid()); + FinishCoredumpCb(getpid(), fileName, retCode); + }; + + std::thread t(threadFunc); + t.detach(); + auto ret = SaveCoredumpToFileTimeout(getpid()); + ASSERT_EQ(ret, "com.ohos.sceneboard.dmp"); + GTEST_LOG_(INFO) << "CoreDumpCbTest002: end."; +} + +/** + * @tc.name: CoreDumpCbTest003 + * @tc.desc: Test coredump cancel process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoreDumpCbTest003, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest003: start."; + auto threadFunc = []() { + sleep(1); + ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::REQUEST_SUCCESS); + StartCoredumpCb(getpid(), getpid()); // to clean processmap + }; + + std::thread t(threadFunc); + t.detach(); + auto ret = SaveCoredumpToFileTimeout(getpid()); + ASSERT_EQ(ret, ""); + GTEST_LOG_(INFO) << "CoreDumpCbTest003: end."; +} + +/** + * @tc.name: CoreDumpCbTest004 + * @tc.desc: Test coredump cancel process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoreDumpCbTest004, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest004: start."; + auto threadFunc = []() { + sleep(1); + StartCoredumpCb(getpid(), getpid()); + ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::REQUEST_SUCCESS); + }; + + std::thread t(threadFunc); + t.detach(); + auto ret = SaveCoredumpToFileTimeout(getpid()); + ASSERT_EQ(ret, ""); + GTEST_LOG_(INFO) << "CoreDumpCbTest004: end."; +} + +/** + * @tc.name: CoreDumpCbTest005 + * @tc.desc: Test coredump cancel process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoreDumpCbTest005, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest005: start."; + ASSERT_EQ(CancelCoredump(getpid()), ResponseCode::DEFAULT_ERROR_CODE); + GTEST_LOG_(INFO) << "CoreDumpCbTest005: end."; +} + +/** + * @tc.name: CoreDumpCbTest006 + * @tc.desc: Test coredump repeat process + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoreDumpCbTest006, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest006: start."; + int32_t retCode = ResponseCode::REQUEST_SUCCESS; + std::string fileName = "com.ohos.sceneboard.dmp"; + + auto threadFunc = [&fileName, retCode]() { + sleep(1); + ASSERT_EQ(SaveCoredumpToFileTimeout(getpid()), ""); + StartCoredumpCb(getpid(), getpid()); + FinishCoredumpCb(getpid(), fileName, retCode); + }; + + std::thread t(threadFunc); + t.detach(); + auto ret = SaveCoredumpToFileTimeout(getpid()); + ASSERT_EQ(ret, "com.ohos.sceneboard.dmp"); + GTEST_LOG_(INFO) << "CoreDumpCbTest006: end."; +} + +/** + * @tc.name: CoreDumpCbTest007 + * @tc.desc: Test coredump process when targetPid = -1 + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoreDumpCbTest007, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoreDumpCbTest007: start."; + int32_t targetPid = -1; + int32_t retCode = ResponseCode::REQUEST_SUCCESS; + std::string fileName = "com.ohos.sceneboard.dmp"; + ASSERT_EQ(SaveCoredumpToFileTimeout(targetPid), ""); + ASSERT_EQ(CancelCoredump(targetPid), ResponseCode::DEFAULT_ERROR_CODE); + ASSERT_EQ(StartCoredumpCb(targetPid, getpid()), ResponseCode::DEFAULT_ERROR_CODE); + ASSERT_EQ(FinishCoredumpCb(targetPid, fileName, retCode), ResponseCode::DEFAULT_ERROR_CODE); + GTEST_LOG_(INFO) << "CoreDumpCbTest007: end."; +} + +/** + * @tc.name: CoredumpSessionService001 + * @tc.desc: test CoredumpSessionService + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoredumpSessionService001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoredumpSessionService001: start."; + CoredumpSessionService sessionService; + + CreateCoredumpRequest request; + pid_t testPid = 666; + pid_t validPid = 999; + request.targetPid = 666; + + auto sessionId = sessionService.CreateSession(request); + EXPECT_EQ(sessionId, testPid); + + auto ret = sessionService.UpdateWorkerPid(sessionId, 124); + EXPECT_TRUE(ret); + ret = sessionService.UpdateWorkerPid(validPid, 124); + EXPECT_FALSE(ret); + + CoredumpCallbackReport reportReq; + sessionService.UpdateReport(sessionId, reportReq); + sessionService.UpdateReport(validPid, reportReq); + + sessionService.GetClientFd(sessionId); + sessionService.GetClientFd(validPid); + + sessionService.WriteTimeoutAndClose(sessionId); + sessionService.WriteTimeoutAndClose(validPid); + + sessionService.WriteResultAndClose(sessionId); + sessionService.WriteResultAndClose(validPid); + + CoreDumpResult result; + sessionService.WriteResult(sessionId, result); + sessionService.WriteResult(validPid, result); + + ret = sessionService.CancelSession(sessionId); + ret = sessionService.CancelSession(validPid); + EXPECT_FALSE(ret); + + GTEST_LOG_(INFO) << "CoredumpSessionService001: end."; +} + +/** + * @tc.name: FaultCoredumpConfig001 + * @tc.desc: test FaultCoredumpConfig + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, FaultCoredumpConfig001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "FaultCoredumpConfig001: start."; + FaultCoredumpConfig::GetInstance(); + + string path = "/system/etc/fault_coredump.json"; + auto& coredumpConfig = FaultCoredumpConfig::GetInstance(path); + + coredumpConfig.Contains(999); + + std::string content = R"({ + "Profiles": { + + })"; + auto ret = coredumpConfig.Parse(content); + EXPECT_FALSE(ret); + + content = R"({ + "Profiles": { + } + })"; + + ret = coredumpConfig.Parse(content); + EXPECT_FALSE(ret); + + content = R"({ + "whitelist": 123 + })"; + ret = coredumpConfig.Parse(content); + EXPECT_FALSE(ret); + content = R"({ + "whitelist": ["ABC"] + })"; + ret = coredumpConfig.Parse(content); + + content = R"({ + "whitelist": [0, 134] + })"; + ret = coredumpConfig.Parse(content); + EXPECT_TRUE(ret); + + GTEST_LOG_(INFO) << "FaultCoredumpConfig001: end."; +} + +/** + * @tc.name: CoredumpRequestValidator001 + * @tc.desc: test CoredumpRequestValidator + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoredumpRequestValidator001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoredumpRequestValidator001: start."; + CoredumpRequestValidator validator; + std::string socketName = "server"; + int32_t connectionFd = -1; + CoreDumpRequestData request; + request.pid = -1; + validator.ValidateRequest(socketName, -1, request); + + request.pid = 666; + validator.ValidateRequest(socketName, -1, request); + + socketName = "faultloggerd.server"; + validator.ValidateRequest(socketName, -1, request); + + auto ret = CoredumpRequestValidator::CheckCoredumpUID(9999); + EXPECT_FALSE(ret); + + int fd = open("dev/null", O_RDONLY); + CoredumpRequestValidator::IsAuthorizedUid(fd); + close(fd); + + GTEST_LOG_(INFO) << "CoredumpRequestValidator001: end."; +} + +/** + * @tc.name: CoredumpFacade001 + * @tc.desc: test facade + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoredumpFacade001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoredumpFacade001: start."; + + CoredumpFacade facade; + CreateCoredumpRequest request; + request.targetPid = 666; + bool ret = facade.CreateCoredump(request); + EXPECT_TRUE(ret); + + facade.OnTimeout(666); + facade.OnTimeout(999); + + request.targetPid = 555; + facade.CreateCoredump(request); + facade.CancelCoredump(999); + facade.CancelCoredump(555); + + GTEST_LOG_(INFO) << "CoredumpFacade001: end."; +} + +/** + * @tc.name: SessionStateContext001 + * @tc.desc: test SessionStateContext + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, SessionStateContext001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "SessionStateContext001: start."; + + auto ret = SessionStateContext::CreateState(CoredumpStatus::PENDING); + EXPECT_TRUE(ret); + SessionStateContext::CreateState(CoredumpStatus::RUNNING); + SessionStateContext::CreateState(CoredumpStatus::SUCCESS); + SessionStateContext::CreateState(CoredumpStatus::FAILED); + SessionStateContext::CreateState(CoredumpStatus::CANCEL_PENDING); + SessionStateContext::CreateState(CoredumpStatus::CANCELED); + SessionStateContext::CreateState(CoredumpStatus::CANCEL_TIMEOUT); + SessionStateContext::CreateState(CoredumpStatus::PENDING); + ret = SessionStateContext::CreateState(CoredumpStatus::INVALID_STATUS); + EXPECT_FALSE(ret); + + SessionStateContext stateContext; + CoredumpEvent event = CoredumpEvent::TIMEOUT; + CoredumpSession session; + session.status = CoredumpStatus::INVALID_STATUS; + stateContext.HandleEvent(session, event); + + GTEST_LOG_(INFO) << "SessionStateContext001: end."; +} + +/** + * @tc.name: SessionStateContext002 + * @tc.desc: RecorderProcessMap + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, SessionStateContext002, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "SessionStateContext002: start."; + SessionStateContext stateContext; + CoredumpEvent event = CoredumpEvent::INVALID_EVENT; + + CoredumpSession session; + session.status = CoredumpStatus::INVALID_STATUS; + stateContext.HandleEvent(session, event); + + auto pendingState = SessionStateContext::CreateState(CoredumpStatus::PENDING); + pendingState->OnEvent(CoredumpEvent::INVALID_EVENT, session); + + auto runningState = SessionStateContext::CreateState(CoredumpStatus::RUNNING); + runningState->OnEvent(CoredumpEvent::REPORT_FAIL, session); + runningState->OnEvent(CoredumpEvent::INVALID_EVENT, session); + + auto cancelPendingState = SessionStateContext::CreateState(CoredumpStatus::CANCEL_PENDING); + cancelPendingState->OnEvent(CoredumpEvent::TIMEOUT, session); + cancelPendingState->OnEvent(CoredumpEvent::INVALID_EVENT, session); + EXPECT_TRUE(cancelPendingState); + + pendingState->OnEvent(CoredumpEvent::INVALID_EVENT, session); + GTEST_LOG_(INFO) << "SessionStateContext002: end."; +} + +/** + * @tc.name: CoredumpCallbackValidator001 + * @tc.desc: RecorderProcessMap + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoredumpCallbackValidator001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoredumpCallbackValidator001: start."; + + std::string socketName = "server"; + int32_t connectionFd = 999; + CoreDumpStatusData data; + data.pid = -1; + + auto ret = CoredumpCallbackValidator::ValidateRequest(socketName, connectionFd, data); + EXPECT_EQ(ret, ResponseCode::REQUEST_REJECT); + + data.pid = getpid(); + CoredumpCallbackValidator::ValidateRequest(socketName, connectionFd, data); + EXPECT_EQ(ret, ResponseCode::REQUEST_REJECT); + GTEST_LOG_(INFO) << "CoredumpCallbackValidator001: end."; +} + +/** + * @tc.name: CoredumpTaskScheduler001 + * @tc.desc: RecorderProcessMap + * @tc.type: FUNC + */ +HWTEST_F(FaultloggerdCoredumpTest, CoredumpTaskScheduler001, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "CoredumpTaskScheduler001: start."; + + CoredumpTaskScheduler scheduler; + auto& sessionManager = CoredumpSessionManager::Instance(); + + CreateCoredumpRequest request; + request.targetPid = 666; + request.endTime = GetAbsTimeMilliSeconds(); + scheduler.ScheduleCancelTime(request.targetPid, 1 * 1000); + sessionManager.CreateSession(request); + scheduler.ScheduleCancelTime(request.targetPid, 1 * 1000); + CoredumpSession* session = sessionManager.GetSession(request.targetPid); + EXPECT_TRUE(session); + sleep(2); + session = sessionManager.GetSession(request.targetPid); + GTEST_LOG_(INFO) << "CoredumpTaskScheduler001: end."; + + scheduler.CancelTimeout(-999); +} +} // namespace HiviewDFX +} // namepsace OHOS diff --git a/test/unittest/kernel_snapshot/kernel_snapshot_test.cpp b/test/unittest/kernel_snapshot/kernel_snapshot_test.cpp index b1227faf160535d38106f7f936bb6453de22c1fd..0b77f0256c19f0cbd2f0e63bc24bd009991973de 100644 --- a/test/unittest/kernel_snapshot/kernel_snapshot_test.cpp +++ b/test/unittest/kernel_snapshot/kernel_snapshot_test.cpp @@ -576,18 +576,59 @@ HWTEST_F(KernelSnapshotTest, KernelSnapshotTest051, TestSize.Level2) KernelSnapshotReporter reporter; CrashMap output; - auto ret = reporter.ReportCrashNoLogEvent(output); - ASSERT_FALSE(ret); - output[CrashSection::UID] = "123"; output[CrashSection::PID] = "156"; output[CrashSection::TIME_STAMP] = "152451571481"; output[CrashSection::PROCESS_NAME] = "testProcess"; - ret = reporter.ReportCrashNoLogEvent(output); + auto ret = reporter.ReportCrashNoLogEvent(output); ASSERT_TRUE(ret); GTEST_LOG_(INFO) << "KernelSnapshotTest051: end."; } +/** + * @tc.name: KernelSnapshotReporter002 + * @tc.desc: test ReportRawMsg + * @tc.type: FUNC + */ +HWTEST_F(KernelSnapshotTest, KernelSnapshotReporter002, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "KernelSnapshotReporter002: start."; + KernelSnapshotReporter reporter; + + std::string snapshot; + std::vector outputs; + CrashMap output; + output[CrashSection::UID] = ""; + output[CrashSection::PID] = "156"; + output[CrashSection::TIME_STAMP] = "152451571481"; + output[CrashSection::PROCESS_NAME] = "testProcess"; + outputs.push_back(output); + reporter.ReportEvents(outputs, snapshot); + + auto ret = reporter.ReportRawMsg(snapshot); + EXPECT_FALSE(ret); + snapshot = "kernel_snapshot"; + ret = reporter.ReportRawMsg(snapshot); + EXPECT_TRUE(ret); + GTEST_LOG_(INFO) << "KernelSnapshotReporter002: end."; +} + +/** + * @tc.name: KernelSnapshotReporter003 + * @tc.desc: test GetSnapshotPid + * @tc.type: FUNC + */ +HWTEST_F(KernelSnapshotTest, KernelSnapshotReporter003, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "KernelSnapshotReporter003: start."; + KernelSnapshotReporter reporter; + EXPECT_EQ(reporter.GetSnapshotPid("12)"), 0); + EXPECT_EQ(reporter.GetSnapshotPid("abcpid=123"), 0); + EXPECT_EQ(reporter.GetSnapshotPid("abcpid=abc)"), 0); + EXPECT_EQ(reporter.GetSnapshotPid("abcpid=123)"), 123); + GTEST_LOG_(INFO) << "KernelSnapshotReporter003: end."; +} + /** * @tc.name: KernelSnapshotTest052 * @tc.desc: test kernel snapshot trie insert diff --git a/test/unittest/process_dump/thread_dump_info_test.cpp b/test/unittest/process_dump/thread_dump_info_test.cpp index a5e09de61efa1dfabf8acdc7aeef161a11f806a3..3aba65807ca2bbb3d99110b88a025fd493db5612 100644 --- a/test/unittest/process_dump/thread_dump_info_test.cpp +++ b/test/unittest/process_dump/thread_dump_info_test.cpp @@ -110,7 +110,7 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest001, TestSize.Level2) Unwinder unwinder(pid, nsPid, request.type == ProcessDumpType::DUMP_TYPE_CPP_CRASH); unwinder.EnableFillFrames(false); KeyThreadDumpInfo dumpInfo; - EXPECT_GT(dumpInfo.UnwindStack(process, unwinder), 0); + EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { @@ -167,7 +167,7 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest002, TestSize.Level2) Unwinder unwinder(pid, nsPid, request.type == ProcessDumpType::DUMP_TYPE_CPP_CRASH); unwinder.EnableFillFrames(false); KeyThreadDumpInfo dumpInfo; - EXPECT_GT(dumpInfo.UnwindStack(process, unwinder), 0); + EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { @@ -215,7 +215,7 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest003, TestSize.Level2) Unwinder unwinder(pid, nsPid, request.type == ProcessDumpType::DUMP_TYPE_CPP_CRASH); unwinder.EnableFillFrames(false); KeyThreadDumpInfo dumpInfo; - EXPECT_GT(dumpInfo.UnwindStack(process, unwinder), 0); + EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { @@ -257,7 +257,7 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest004, TestSize.Level2) Unwinder unwinder(pid, nsPid, request.type == ProcessDumpType::DUMP_TYPE_CPP_CRASH); unwinder.EnableFillFrames(false); OtherThreadDumpInfo dumpInfo; - EXPECT_GT(dumpInfo.UnwindStack(process, unwinder), 0); + EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { @@ -300,7 +300,7 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest005, TestSize.Level2) Unwinder unwinder(pid, nsPid, request.type == ProcessDumpType::DUMP_TYPE_CPP_CRASH); unwinder.EnableFillFrames(false); OtherThreadDumpInfo dumpInfo; - EXPECT_GT(dumpInfo.UnwindStack(process, unwinder), 0); + EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), 0); dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { @@ -345,7 +345,7 @@ HWTEST_F(ThreadDumpInfoTest, ThreadDumpInfoTest006, TestSize.Level2) std::shared_ptr keyThreadDumpInfo = std::make_shared(); OtherThreadDumpInfo dumpInfo; dumpInfo.SetDumpInfo(keyThreadDumpInfo); - EXPECT_GT(dumpInfo.UnwindStack(process, unwinder), threadCount); + EXPECT_GT(dumpInfo.UnwindStack(process, request, unwinder), threadCount); dumpInfo.Symbolize(process, unwinder); dumpInfo.Print(process, request, unwinder); std::vector keyWords = { diff --git a/tools/process_dump/decorative_dump_info.h b/tools/process_dump/decorative_dump_info.h index 7698320864dc994136e0334d509f5b6da1fb4fe5..fd7737acc65577317af9a8ddc1f93fe473a8ba58 100644 --- a/tools/process_dump/decorative_dump_info.h +++ b/tools/process_dump/decorative_dump_info.h @@ -50,10 +50,10 @@ public: } } - int UnwindStack(DfxProcess& process, Unwinder& unwinder) override + int UnwindStack(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) override { if (dumpInfo_ != nullptr) { - return dumpInfo_->UnwindStack(process, unwinder); + return dumpInfo_->UnwindStack(process, request, unwinder); } return 0; } @@ -113,7 +113,7 @@ private: class OtherThreadDumpInfo : public DecorativeDumpInfo { public: - int UnwindStack(DfxProcess& process, Unwinder& unwinder) override; + 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/dump_info.h b/tools/process_dump/dump_info.h index cee0b044f03aad2454c2a5f04832d694934d9bb0..28935c9c14cd80e393fe06b349fc6c6d168c66a3 100644 --- a/tools/process_dump/dump_info.h +++ b/tools/process_dump/dump_info.h @@ -31,7 +31,7 @@ public: virtual ~DumpInfo() {} virtual void SetDumpInfo(const std::shared_ptr& dumpInfo) {} virtual void Print(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) = 0; - virtual int UnwindStack(DfxProcess& process, 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 cdc130ac7e28d804e6a9366f4f1f813c9cdcdaf4..c59e7f9e2325775e086627a6cadfb2b6e24766aa 100644 --- a/tools/process_dump/dump_info_json_formatter.cpp +++ b/tools/process_dump/dump_info_json_formatter.cpp @@ -59,6 +59,7 @@ void DumpInfoJsonFormatter::GetCrashJsonFormatInfo(const ProcessDumpRequest& req jsonInfo["time"] = request.timeStamp; jsonInfo["uuid"] = ""; jsonInfo["crash_type"] = "NativeCrash"; + jsonInfo["process_name"] = process.GetProcessInfo().processName; jsonInfo["pid"] = process.GetProcessInfo().pid; jsonInfo["uid"] = process.GetProcessInfo().uid; jsonInfo["app_running_unique_id"] = request.appRunningId; diff --git a/tools/process_dump/key_thread_dump_info.cpp b/tools/process_dump/key_thread_dump_info.cpp index 82b5df759a0669146679f204c63bc950b3727bc4..a76a339a4a1c89f72fa28e762fc0888ad0779b88 100644 --- a/tools/process_dump/key_thread_dump_info.cpp +++ b/tools/process_dump/key_thread_dump_info.cpp @@ -107,7 +107,7 @@ void KeyThreadDumpInfo::Print(DfxProcess& process, const ProcessDumpRequest& req DfxBufferWriter::GetInstance().AppendBriefDumpInfo(dumpInfo); } -int KeyThreadDumpInfo::UnwindStack(DfxProcess& process, Unwinder& unwinder) +int KeyThreadDumpInfo::UnwindStack(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) { DFXLOGI("unwind key thread dump start"); int result = 0; @@ -119,7 +119,7 @@ int KeyThreadDumpInfo::UnwindStack(DfxProcess& process, Unwinder& unwinder) DFXLOGW("vm pid is null, can not unwind key thread!"); return result; } - + unwinder.SetIsJitCrashFlag(request.type == ProcessDumpType::DUMP_TYPE_CPP_CRASH); if (process.GetKeyThread()->GetThreadRegs() != nullptr) { result = GetKeyThreadStack(process, unwinder) ? 1 : 0; } else { diff --git a/tools/process_dump/key_thread_dump_info.h b/tools/process_dump/key_thread_dump_info.h index 4dd716a1cb2e433d5b4df0a46893f5ef98adf3ec..f2ef6f9c988eab4ca1f03e19aecee4494596519d 100644 --- a/tools/process_dump/key_thread_dump_info.h +++ b/tools/process_dump/key_thread_dump_info.h @@ -28,7 +28,7 @@ namespace HiviewDFX { class KeyThreadDumpInfo : public DumpInfo { public: void Print(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) override; - int UnwindStack(DfxProcess& process, 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: diff --git a/tools/process_dump/lperf/lperf_events.cpp b/tools/process_dump/lperf/lperf_events.cpp index d10cf989b56f9bc59e542f319f7b9d4ec0741e7f..ea85e4b103f59231e28a6be6295df25132162841 100644 --- a/tools/process_dump/lperf/lperf_events.cpp +++ b/tools/process_dump/lperf/lperf_events.cpp @@ -178,7 +178,7 @@ void LperfEvents::GetRecordFieldFromMmap(MmapFd& mmap, void* dest, size_t destSi if (memcpy_s(dest, destSize, mmap.buf + pos, copySize) != 0) { DFXLOGE("memcpy_s failed. size %{public}zd", copySize); } - if (copySize < size) { + if (copySize < size && destSize > copySize) { size -= copySize; if (memcpy_s(static_cast(dest) + copySize, destSize - copySize, mmap.buf, size) != 0) { DFXLOGE("memcpy_s mmap.buf to dest failed. size %{public}zd", size); diff --git a/tools/process_dump/other_thread_dump_info.cpp b/tools/process_dump/other_thread_dump_info.cpp index 1bb1802290e5d7fa458505f742d2a008829fb655..1acd9396a3164a63ba6d87abfca536269839de35 100644 --- a/tools/process_dump/other_thread_dump_info.cpp +++ b/tools/process_dump/other_thread_dump_info.cpp @@ -23,9 +23,9 @@ namespace OHOS { namespace HiviewDFX { REGISTER_DUMP_INFO_CLASS(OtherThreadDumpInfo); -int OtherThreadDumpInfo::UnwindStack(DfxProcess& process, Unwinder& unwinder) +int OtherThreadDumpInfo::UnwindStack(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder) { - int unwindSuccessCnt = DecorativeDumpInfo::UnwindStack(process, unwinder); + int unwindSuccessCnt = DecorativeDumpInfo::UnwindStack(process, request, unwinder); DFXLOGI("unwind other thread dump start"); auto pid = process.GetVmPid(); if (pid == 0) { diff --git a/tools/process_dump/process_dumper.cpp b/tools/process_dump/process_dumper.cpp index f22eb02cbd3d60492bd8c54246c5b295a53ec392..ab6fdaea172eaccc2eeec62b731935bcaa25b506 100644 --- a/tools/process_dump/process_dumper.cpp +++ b/tools/process_dump/process_dumper.cpp @@ -437,7 +437,7 @@ void ProcessDumper::PrintDumpInfo(int& dumpRes) prevDumpInfo = dumpInfo; } if (threadDumpInfo != nullptr) { - int unwindSuccessCnt = threadDumpInfo->UnwindStack(*process_, *unwinder_); + int unwindSuccessCnt = threadDumpInfo->UnwindStack(*process_, request_, *unwinder_); DFXLOGI("unwind success thread count(%{public}d)", unwindSuccessCnt); if (unwindSuccessCnt > 0) { dumpRes = ParseSymbols(threadDumpInfo);