From be5c8b55e7c9b58f38605422c2ab8eae0b5e3c55 Mon Sep 17 00:00:00 2001 From: yuhaoqiang Date: Sat, 30 Aug 2025 09:57:58 +0800 Subject: [PATCH] =?UTF-8?q?faultloggerd=20ram=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yuhaoqiang Change-Id: Ib79bd38a0496f33c97426503e25dadf221c6eb76 Signed-off-by: yuhaoqiang --- BUILD.gn | 1 + services/BUILD.gn | 10 +- services/epoll_manager.cpp | 54 +++++--- services/epoll_manager.h | 18 ++- services/fault_logger_daemon.cpp | 9 ++ ...t_manager.cpp => kernel_snapshot_task.cpp} | 118 ++++++++---------- ...pshot_manager.h => kernel_snapshot_task.h} | 22 ++-- services/main.cpp | 6 - services/snapshot/BUILD.gn | 38 ++++++ services/snapshot/kernel_snapshot.map | 10 ++ services/snapshot/kernel_snapshot_parser.cpp | 4 +- services/snapshot/kernel_snapshot_printer.cpp | 1 - .../kernel_snapshot_processor_impl.cpp | 5 + .../snapshot/kernel_snapshot_processor_impl.h | 8 ++ test/resource/ohos_test.xml | 5 + test/unittest/faultloggerd/BUILD.gn | 1 + test/unittest/kernel_snapshot/BUILD.gn | 1 - .../kernel_snapshot/kernel_snapshot_test.cpp | 4 +- 18 files changed, 194 insertions(+), 121 deletions(-) rename services/{snapshot/kernel_snapshot_manager.cpp => kernel_snapshot_task.cpp} (30%) rename services/{snapshot/kernel_snapshot_manager.h => kernel_snapshot_task.h} (60%) create mode 100644 services/snapshot/BUILD.gn create mode 100644 services/snapshot/kernel_snapshot.map diff --git a/BUILD.gn b/BUILD.gn index 7f9298e59..e8e61c751 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -29,6 +29,7 @@ group("faultloggerd_targets") { "interfaces/innerkits/stack_printer:libstack_printer", "interfaces/innerkits/unwinder:libunwinder", "interfaces/rust:faultloggerd_rust", + "services/snapshot:kernel_snapshot", "tools/dump_catcher:dumpcatcher", ] if (faultloggerd_hisysevent_enable) { diff --git a/services/BUILD.gn b/services/BUILD.gn index 720a9d10b..082c6155b 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -85,15 +85,8 @@ if (defined(ohos_lite)) { "./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", - "./snapshot/kernel_snapshot_parser.cpp", - "./snapshot/kernel_snapshot_printer.cpp", - "./snapshot/kernel_snapshot_processor_impl.cpp", - "./snapshot/kernel_snapshot_reporter.cpp", - "./snapshot/kernel_snapshot_trie.cpp", "fault_logger_pipe.cpp", + "kernel_snapshot_task.cpp", ] config("faultloggerd_config") { @@ -102,7 +95,6 @@ if (defined(ohos_lite)) { include_dirs = [ ".", "./coredump", - "./snapshot", "$faultloggerd_interfaces_path/common", "$faultloggerd_path/common/dfxlog", "$faultloggerd_path/common/dfxutil", diff --git a/services/epoll_manager.cpp b/services/epoll_manager.cpp index e15d63f5c..e0ba8d9a1 100644 --- a/services/epoll_manager.cpp +++ b/services/epoll_manager.cpp @@ -174,37 +174,63 @@ void EpollManager::StopEpoll() } } -std::unique_ptr DelayTask::CreateInstance(std::function workFunc, int32_t timeout) +SmartFd TimerTask::CreateTimeFd() { - if (timeout <= 0) { - return nullptr; - } SmartFd timefd{timerfd_create(CLOCK_MONOTONIC, 0)}; if (!timefd) { DFXLOGE("%{public}s :: failed to create time fd, errno: %{public}d", EPOLL_MANAGER, errno); - return nullptr; + } + return timefd; +} + +TimerTask::TimerTask(bool persist) : EpollListener(CreateTimeFd(), persist) {} + +bool TimerTask::SetTimeOption(int32_t delayTime, int32_t periodicity) +{ + if (GetFd() < 0) { + return false; } struct itimerspec timeOption{}; - timeOption.it_value.tv_sec = timeout; - if (timerfd_settime(timefd.GetFd(), 0, &timeOption, nullptr) == -1) { + timeOption.it_value.tv_sec = delayTime; + timeOption.it_interval.tv_sec = periodicity; + if (timerfd_settime(GetFd(), 0, &timeOption, nullptr) == -1) { DFXLOGE("%{public}s :: failed to set delay time for fd, errno: %{public}d.", EPOLL_MANAGER, errno); - return nullptr; + return false; } - return std::unique_ptr(new (std::nothrow)DelayTask(workFunc, std::move(timefd))); + return true; } -DelayTask::DelayTask(std::function workFunc, SmartFd timeFd) - : EpollListener(std::move(timeFd)), work_(std::move(workFunc)) {} - -void DelayTask::OnEventPoll() +void TimerTask::OnEventPoll() { uint64_t exp = 0; auto ret = OHOS_TEMP_FAILURE_RETRY(read(GetFd(), &exp, sizeof(exp))); if (ret < 0 || static_cast(ret) != sizeof(exp)) { DFXLOGE("%{public}s :: failed read time fd %{public}" PRId32, EPOLL_MANAGER, GetFd()); } else { - work_(); + OnTimer(); } } + +std::unique_ptr DelayTask::CreateInstance(std::function workFunc, int32_t timeout) +{ + if (timeout <= 0) { + return nullptr; + } + auto delayTask = std::unique_ptr(new (std::nothrow)DelayTask(workFunc)); + if (!delayTask) { + return nullptr; + } + if (delayTask->SetTimeOption(timeout, 0)) { + return delayTask; + } + return nullptr; +} + +DelayTask::DelayTask(std::function workFunc) : TimerTask(false), work_(std::move(workFunc)) {} + +void DelayTask::OnTimer() +{ + work_(); +} } } \ No newline at end of file diff --git a/services/epoll_manager.h b/services/epoll_manager.h index 4026e2bcb..93ef4e88e 100644 --- a/services/epoll_manager.h +++ b/services/epoll_manager.h @@ -59,14 +59,26 @@ private: std::mutex epollMutex_; }; -class DelayTask : public EpollListener { +class TimerTask : public EpollListener { +public: + explicit TimerTask(bool persist); + ~TimerTask() override = default; + void OnEventPoll() final; +protected: + virtual void OnTimer() = 0; + bool SetTimeOption(int32_t delayTime, int32_t periodicity); +private: + static SmartFd CreateTimeFd(); +}; + +class DelayTask : public TimerTask { public: DelayTask(const DelayTask&) = delete; DelayTask& operator=(const DelayTask&) = delete; static std::unique_ptr CreateInstance(std::function workFunc, int32_t timeout); - void OnEventPoll() override; + void OnTimer() override; private: - DelayTask(std::function workFunc, SmartFd timeFd); + explicit DelayTask(std::function workFunc); std::function work_; }; } diff --git a/services/fault_logger_daemon.cpp b/services/fault_logger_daemon.cpp index afe6ff6e1..d1d660711 100644 --- a/services/fault_logger_daemon.cpp +++ b/services/fault_logger_daemon.cpp @@ -24,6 +24,10 @@ #include "epoll_manager.h" #include "fault_logger_server.h" +#ifndef is_ohos_lite +#include "kernel_snapshot_task.h" +#endif + namespace OHOS { namespace HiviewDFX { @@ -57,6 +61,11 @@ FaultLoggerDaemon::FaultLoggerDaemon() : mainServer_(mainEpollManager_), tempFil DFXLOGE("%{public}s :: Failed to init tempFileManager", FAULTLOGGERD_DAEMON_TAG); return; } +#ifndef is_ohos_lite + if (OHOS::HiviewDFX::IsBetaVersion()) { + secondaryEpollManager_.AddListener(std::make_unique()); + } +#endif if (signal(SIGCHLD, SIG_IGN) == SIG_ERR || signal(SIGPIPE, SIG_IGN) == SIG_ERR) { DFXLOGE("%{public}s :: Failed to signal SIGCHLD or SIGPIPE, errno: %{public}d", FAULTLOGGERD_DAEMON_TAG, errno); diff --git a/services/snapshot/kernel_snapshot_manager.cpp b/services/kernel_snapshot_task.cpp similarity index 30% rename from services/snapshot/kernel_snapshot_manager.cpp rename to services/kernel_snapshot_task.cpp index 70828cc0f..817870c14 100644 --- a/services/snapshot/kernel_snapshot_manager.cpp +++ b/services/kernel_snapshot_task.cpp @@ -13,101 +13,85 @@ * limitations under the License. */ -#include "kernel_snapshot_manager.h" +#include "kernel_snapshot_task.h" -#include +#include #include -#include -#include -#include - -#include "parameters.h" +#include #include "dfx_log.h" -#include "dfx_util.h" - -#include "kernel_snapshot_content_builder.h" -#include "kernel_snapshot_processor_impl.h" +#include "parameters.h" #include "smart_fd.h" namespace OHOS { namespace HiviewDFX { -namespace { -constexpr const char * const KERNEL_KBOX_SNAPSHOT = "/sys/kbox/snapshot_clear"; -constexpr const char * const KERNEL_SNAPSHOT_INTERVAL = "kernel_snapshot_check_interval"; -constexpr int BUFFER_LEN = 1024; -constexpr int DEFAULT_INTERVAL = 60; -constexpr int MIN_INTERVAL = 3; -} -int KernelSnapshotManager::GetSnapshotCheckInterval() -{ - static int value = OHOS::system::GetIntParameter(KERNEL_SNAPSHOT_INTERVAL, DEFAULT_INTERVAL); - value = std::max(value, MIN_INTERVAL); - DFXLOGI("monitor crash kernel snapshot interval %{public}d", value); - return value; -} - -std::string KernelSnapshotManager::ReadKernelSnapshot() +namespace { +std::string ReadKernelSnapshot() { - SmartFd snapshotFd(open(KERNEL_KBOX_SNAPSHOT, O_RDONLY)); - if (!snapshotFd) { - DFXLOGE("open snapshot filed %{public}d", errno); +#ifdef FAULTLOGGERD_TEST + constexpr auto kernelKboxSnapshot = "/data/test/resource/testdata/kernel_snapshot_execption.txt"; +#else + constexpr auto kernelKboxSnapshot = "/sys/kbox/snapshot_clear"; +#endif + SmartFd fd(open(kernelKboxSnapshot, O_RDONLY)); + if (!fd) { + DFXLOGE("open snapshot %{public}s failed %{public}d", kernelKboxSnapshot, errno); return ""; } - - char buffer[BUFFER_LEN] = {0}; + constexpr int buffLength = 1024; + char buffer[buffLength] = {0}; std::string snapshotCont; ssize_t ret = 0; do { - ret = read(snapshotFd.GetFd(), buffer, BUFFER_LEN - 1); + ret = read(fd.GetFd(), buffer, buffLength - 1); if (ret > 0) { snapshotCont.append(buffer, static_cast(ret)); } if (ret < 0) { - DFXLOGE("read snapshot filed %{public}d", errno); + DFXLOGE("read snapshot failed %{public}d", errno); } } while (ret > 0); - if (!snapshotCont.empty()) { - DFXLOGI("read snapshot begin with %{public}s", snapshotCont.substr(0, 25).c_str()); // 25 : only need 25 - } return snapshotCont; } +} -void KernelSnapshotManager::MonitorCrashKernelSnapshot() +ReadKernelSnapshotTask::ReadKernelSnapshotTask() : TimerTask(true) { - DFXLOGI("enter %{public}s ", __func__); - pthread_setname_np(pthread_self(), "KernelSnapshot"); - int interval = GetSnapshotCheckInterval(); - - std::unique_ptr processor(new KernelSnapshotProcessorImpl()); - - while (true) { - std::this_thread::sleep_for(std::chrono::seconds(interval)); - if (access(KERNEL_KBOX_SNAPSHOT, F_OK) < 0) { - DFXLOGE("can't find %{public}s, just exit", KERNEL_KBOX_SNAPSHOT); - break; - } - std::string snapshotCont = ReadKernelSnapshot(); - if (snapshotCont.empty()) { - continue; - } - processor->Process(snapshotCont); - } + constexpr int minInterval = 3; + constexpr auto kernelSnapshotInterval = "kernel_snapshot_check_interval"; + constexpr int defaultInterval = 60; + int interval = std::max(system::GetIntParameter(kernelSnapshotInterval, defaultInterval), minInterval); +#ifdef FAULTLOGGERD_TEST + SetTimeOption(minInterval, interval); +#else + SetTimeOption(interval, interval); +#endif } -void KernelSnapshotManager::StartMonitor() +void ReadKernelSnapshotTask::OnTimer() { - DFXLOGI("monitor kernel crash snapshot start!"); - if (!IsBetaVersion()) { - DFXLOGW("monitor kernel crash snapshot func not support"); + const std::string snapshotCont = ReadKernelSnapshot(); + if (snapshotCont.empty()) { + DFXLOGD("the snapshot file does not exist or is empty."); return; } - std::thread catchThread = std::thread([] { - KernelSnapshotManager kernelSnapshotManager; - kernelSnapshotManager.MonitorCrashKernelSnapshot(); - }); - catchThread.detach(); + DFXLOGI("read snapshot begin with %{public}s", snapshotCont.substr(0, 25).c_str()); // 25 : only need 25 + constexpr auto kernelSnapshotLibraryName = "libkernel_snapshot.z.so"; + void* handle = dlopen(kernelSnapshotLibraryName, RTLD_LAZY); + if (handle == nullptr) { + DFXLOGE("failed dlopen library %{public}s for error %{public}d", kernelSnapshotLibraryName, errno); + return; + } + constexpr auto methodName = "ProcessKernelSnapShot"; + auto processKernelSnapShot = reinterpret_cast(dlsym(handle, methodName)); + if (processKernelSnapShot == nullptr) { + DFXLOGE("can't find method %{public}s in %{public}s, just exit", methodName, kernelSnapshotLibraryName); + dlclose(handle); + return; + } + processKernelSnapShot(snapshotCont); + dlclose(handle); +} } -} // namespace HiviewDFX -} // namespace OHOS +} \ No newline at end of file diff --git a/services/snapshot/kernel_snapshot_manager.h b/services/kernel_snapshot_task.h similarity index 60% rename from services/snapshot/kernel_snapshot_manager.h rename to services/kernel_snapshot_task.h index f252365aa..54112d398 100644 --- a/services/snapshot/kernel_snapshot_manager.h +++ b/services/kernel_snapshot_task.h @@ -12,24 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef KERNEL_SNAPSHOT_TASK_H_ +#define KERNEL_SNAPSHOT_TASK_H_ +#include "epoll_manager.h" -#ifndef KERNEL_SNAPSHOT_MANAGER_H -#define KERNEL_SNAPSHOT_MANAGER_H - -#include namespace OHOS { namespace HiviewDFX { -class KernelSnapshotManager { +class ReadKernelSnapshotTask : public TimerTask { public: - KernelSnapshotManager(const KernelSnapshotManager&) = delete; - KernelSnapshotManager& operator=(const KernelSnapshotManager&) = delete; - static void StartMonitor(); -private: - KernelSnapshotManager() = default; - void MonitorCrashKernelSnapshot(); - int GetSnapshotCheckInterval(); - std::string ReadKernelSnapshot(); + ReadKernelSnapshotTask(); +protected: + void OnTimer() override; }; } // namespace HiviewDFX } // namespace OHOS -#endif +#endif \ No newline at end of file diff --git a/services/main.cpp b/services/main.cpp index 33156474d..cc7eea6e1 100644 --- a/services/main.cpp +++ b/services/main.cpp @@ -13,9 +13,6 @@ * limitations under the License. */ -#ifndef is_ohos_lite -#include "kernel_snapshot_manager.h" -#endif #include "fault_logger_daemon.h" #if defined(DEBUG_CRASH_LOCAL_HANDLER) && !defined(DFX_ALLOCATE_ASAN) @@ -39,9 +36,6 @@ int main(int argc, char *argv[]) #if defined(DEBUG_CRASH_LOCAL_HANDLER) && !defined(DFX_ALLOCATE_ASAN) DFX_GetCrashFdFunc(DoGetCrashFd); DFX_InstallLocalSignalHandler(); -#endif -#ifndef is_ohos_lite - OHOS::HiviewDFX::KernelSnapshotManager::StartMonitor(); #endif auto& faultLoggerDaemon = OHOS::HiviewDFX::FaultLoggerDaemon::GetInstance(); faultLoggerDaemon.StartServer(); diff --git a/services/snapshot/BUILD.gn b/services/snapshot/BUILD.gn new file mode 100644 index 000000000..3e0efdb22 --- /dev/null +++ b/services/snapshot/BUILD.gn @@ -0,0 +1,38 @@ +# 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. + +import("//base/hiviewdfx/faultloggerd/faultloggerd.gni") + +ohos_shared_library("kernel_snapshot") { + branch_protector_ret = "pac_ret" + install_enable = true + sources = [ + "kernel_snapshot_content_builder.cpp", + "kernel_snapshot_kernel_frame.cpp", + "kernel_snapshot_parser.cpp", + "kernel_snapshot_printer.cpp", + "kernel_snapshot_processor_impl.cpp", + "kernel_snapshot_reporter.cpp", + "kernel_snapshot_trie.cpp", + ] + version_script = "kernel_snapshot.map" + deps = [ "$faultloggerd_path/common/dfxutil:dfx_util" ] + external_deps = [ + "hilog:libhilog", + "hisysevent:libhisysevent", + "init:libbegetutil", + ] + install_images = [ "system" ] + part_name = "faultloggerd" + subsystem_name = "hiviewdfx" +} \ No newline at end of file diff --git a/services/snapshot/kernel_snapshot.map b/services/snapshot/kernel_snapshot.map new file mode 100644 index 000000000..dde212431 --- /dev/null +++ b/services/snapshot/kernel_snapshot.map @@ -0,0 +1,10 @@ +{ + global: + extern "C" { + ProcessKernelSnapShot*; + }; + extern "C++" { + }; + local: + *; +}; \ No newline at end of file diff --git a/services/snapshot/kernel_snapshot_parser.cpp b/services/snapshot/kernel_snapshot_parser.cpp index 063d963c1..461830120 100644 --- a/services/snapshot/kernel_snapshot_parser.cpp +++ b/services/snapshot/kernel_snapshot_parser.cpp @@ -16,8 +16,6 @@ #include "kernel_snapshot_parser.h" #include "dfx_log.h" -#include "string_util.h" - #include "kernel_snapshot_kernel_frame.h" namespace OHOS { @@ -228,7 +226,7 @@ bool KernelSnapshotParser::ProcessTransStart(const std::vector& lin std::string keyword, CrashMap& output) { for (; index < lines.size(); index++) { - if (StartsWith(lines[index], keyword)) { + if (lines[index].size() >= keyword.size() && std::equal(keyword.begin(), keyword.end(), lines[index].begin())) { break; } } diff --git a/services/snapshot/kernel_snapshot_printer.cpp b/services/snapshot/kernel_snapshot_printer.cpp index 67d5e7203..1e9a4e068 100644 --- a/services/snapshot/kernel_snapshot_printer.cpp +++ b/services/snapshot/kernel_snapshot_printer.cpp @@ -16,7 +16,6 @@ #include "kernel_snapshot_printer.h" #include "dfx_log.h" -#include "string_util.h" #include "kernel_snapshot_content_builder.h" namespace OHOS { diff --git a/services/snapshot/kernel_snapshot_processor_impl.cpp b/services/snapshot/kernel_snapshot_processor_impl.cpp index c11de4350..6edde1c55 100644 --- a/services/snapshot/kernel_snapshot_processor_impl.cpp +++ b/services/snapshot/kernel_snapshot_processor_impl.cpp @@ -41,3 +41,8 @@ void KernelSnapshotProcessorImpl::Process(const std::string& snapshot) } } // namespace HiviewDFX } // namespace OHOS + +void ProcessKernelSnapShot(const std::string& kernelSnapShotMsg) +{ + OHOS::HiviewDFX::KernelSnapshotProcessorImpl().Process(kernelSnapShotMsg); +} \ No newline at end of file diff --git a/services/snapshot/kernel_snapshot_processor_impl.h b/services/snapshot/kernel_snapshot_processor_impl.h index 5b49611e0..101f287f9 100644 --- a/services/snapshot/kernel_snapshot_processor_impl.h +++ b/services/snapshot/kernel_snapshot_processor_impl.h @@ -40,4 +40,12 @@ private: }; } // namespace HiviewDFX } // namespace OHOS + +#ifdef __cplusplus +extern "C" { +#endif +void ProcessKernelSnapShot(const std::string& kernelSnapShotMsg); +#ifdef __cplusplus +} +#endif #endif diff --git a/test/resource/ohos_test.xml b/test/resource/ohos_test.xml index 0b979ae3e..043f8b4ec 100644 --- a/test/resource/ohos_test.xml +++ b/test/resource/ohos_test.xml @@ -64,6 +64,11 @@