• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "faultlog_bootscan.h"
16 
17 #include "constants.h"
18 #include "event_publish.h"
19 #include "faultlog_formatter.h"
20 #include "faultlog_util.h"
21 #include "faultlog_processor_factory.h"
22 #include "file_util.h"
23 #include "hisysevent.h"
24 #include "hiview_logger.h"
25 #include "sanitizer_telemetry.h"
26 
27 namespace OHOS {
28 namespace HiviewDFX {
29 DEFINE_LOG_LABEL(0xD002D11, "Faultlogger");
30 
31 namespace {
32 constexpr time_t FORTYEIGHT_HOURS = 48 * 60 * 60;
33 }
34 using namespace FaultLogger;
35 
IsCrashType(const std::string & file)36 bool FaultLogBootScan::IsCrashType(const std::string& file)
37 {
38     // if file type is not cppcrash, skip!
39     if (file.find("cppcrash") == std::string::npos) {
40         HIVIEW_LOGI("Skip this file(%{public}s) that the type is not cppcrash.", file.c_str());
41         return false;
42     }
43     return true;
44 }
45 
IsInValidTime(const std::string & file,const time_t & now)46 bool FaultLogBootScan::IsInValidTime(const std::string& file, const time_t& now)
47 {
48     time_t lastAccessTime = GetFileLastAccessTimeStamp(file);
49     if (now < lastAccessTime) {
50         HIVIEW_LOGI("Skip this file(%{public}s) that current time may be incorrect.", file.c_str());
51         return false;
52     }
53     if (now - lastAccessTime > FORTYEIGHT_HOURS) {
54         HIVIEW_LOGI("Skip this file(%{public}s) that were created 48 hours ago.", file.c_str());
55         return false;
56     }
57     return true;
58 }
59 
IsCrashTempBigFile(const std::string & file)60 bool FaultLogBootScan::IsCrashTempBigFile(const std::string& file)
61 {
62     constexpr uint64_t tempMaxFileSize = 1024 * 1024 * 5;
63     auto fileSize = FileUtil::GetFileSize(file);
64     if (fileSize > tempMaxFileSize) {
65         HIVIEW_LOGI("Skip this file(%{public}s) that file size(%{public}" PRIu64 ") exceeds limit.",
66                     file.c_str(), fileSize);
67         FileUtil::RemoveFile(file);
68         return true;
69     }
70     return false;
71 }
72 
IsEmptyStack(const std::string & file,const FaultLogInfo & info)73 bool FaultLogBootScan::IsEmptyStack(const std::string& file, const FaultLogInfo& info)
74 {
75     if (info.summary.find("#00") == std::string::npos) {
76         HIVIEW_LOGI("Skip this file(%{public}s) which stack is empty.", file.c_str());
77         HiSysEventWrite(HiSysEvent::Domain::RELIABILITY, "CPP_CRASH_NO_LOG", HiSysEvent::EventType::FAULT,
78             FaultKey::MODULE_PID, info.pid,
79             FaultKey::MODULE_UID, info.id,
80             "PROCESS_NAME", info.module,
81             FaultKey::HAPPEN_TIME, std::to_string(info.time)
82         );
83         if (remove(file.c_str()) != 0) {
84             HIVIEW_LOGE("Failed to remove file(%{public}s) which stack is empty", file.c_str());
85         }
86         return true;
87     }
88     return false;
89 }
90 
IsReported(const FaultLogInfo & info)91 bool FaultLogBootScan::IsReported(const FaultLogInfo& info)
92 {
93     if (faultLogManager_->IsProcessedFault(info.pid, info.id, info.faultLogType)) {
94         HIVIEW_LOGI("Skip processed fault.(%{public}d:%{public}d) ", info.pid, info.id);
95         return true;
96     }
97     return false;
98 }
99 
StartBootScan()100 void FaultLogBootScan::StartBootScan()
101 {
102     std::vector<std::string> files;
103     time_t now = time(nullptr);
104     FileUtil::GetDirFiles(FAULTLOG_TEMP_FOLDER, files);
105     for (const auto& file : files) {
106         if (!IsCrashType(file) || !IsInValidTime(file, now) || IsCrashTempBigFile(file)) {
107             continue;
108         }
109 
110         auto info = ParseCppCrashFromFile(file);
111         if (IsEmptyStack(file, info) || IsReported(info)) {
112             continue;
113         }
114         FaultLogProcessorFactory factory;
115         auto processor = factory.CreateFaultLogProcessor(static_cast<FaultLogType>(info.faultLogType));
116         if (processor) {
117             info.sectionMap["START_BOOT_SCAN"] = "true";
118             processor->AddFaultLog(info, workLoop_, faultLogManager_);
119         }
120     }
121 }
122 
AddBootScanEvent()123 void FaultLogBootScan::AddBootScanEvent()
124 {
125     if (workLoop_ == nullptr) {
126         HIVIEW_LOGE("workLoop_ is nullptr.");
127         return;
128     }
129     // some crash happened before hiview start, ensure every crash event is added into eventdb
130     auto task = [this] {
131         StartBootScan();
132     };
133     workLoop_->AddTimerEvent(nullptr, nullptr, task, 60, false); // delay 60 seconds
134 }
135 
FaultLogBootScan(std::shared_ptr<EventLoop> workLoop,std::shared_ptr<FaultLogManager> faultLogManager)136 FaultLogBootScan::FaultLogBootScan(std::shared_ptr<EventLoop> workLoop,
137     std::shared_ptr<FaultLogManager> faultLogManager) : workLoop_(workLoop),  faultLogManager_(faultLogManager)
138 {
139     AddListenerInfo(Event::MessageType::PLUGIN_MAINTENANCE);
140     AddListenerInfo(Event::TELEMETRY_EVENT);
141 }
142 
OnUnorderedEvent(const Event & msg)143 void FaultLogBootScan::OnUnorderedEvent(const Event& msg)
144 {
145     if (msg.messageType_ == Event::TELEMETRY_EVENT) {
146         SanitizerTelemetry sanitizerTelemetry;
147         sanitizerTelemetry.OnUnorderedEvent(msg);
148     }
149 #ifndef UNITTEST
150     if (msg.messageType_ != Event::MessageType::PLUGIN_MAINTENANCE ||
151         msg.eventId_ != Event::EventId::PLUGIN_LOADED) {
152         HIVIEW_LOGE("messageType_(%{public}u), eventId_(%{public}u).", msg.messageType_, msg.eventId_);
153         return;
154     }
155     AddBootScanEvent();
156 #endif
157 }
158 
GetListenerName()159 std::string FaultLogBootScan::GetListenerName()
160 {
161     return "Faultlogger";
162 }
163 } // namespace HiviewDFX
164 } // namespace OHOS
165