1 /*
2 * Copyright (c) 2021-2024 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
16 #include "fault_logger_daemon.h"
17
18 #include <algorithm>
19 #include <cerrno>
20 #include <csignal>
21 #include <cstring>
22 #include <ctime>
23 #include <dirent.h>
24 #include <fcntl.h>
25 #include <fstream>
26 #include <securec.h>
27 #include <sstream>
28 #include <unistd.h>
29 #include <vector>
30
31 #include <sys/epoll.h>
32 #include <sys/socket.h>
33 #include <sys/stat.h>
34 #include <sys/syscall.h>
35 #include <sys/types.h>
36 #include <sys/un.h>
37 #include <sys/wait.h>
38
39 #include "dfx_define.h"
40 #include "dfx_exception.h"
41 #include "dfx_log.h"
42 #include "dfx_trace.h"
43 #include "dfx_util.h"
44 #include "string_printf.h"
45 #include "directory_ex.h"
46 #include "fault_logger_config.h"
47 #include "faultloggerd_socket.h"
48 #ifndef is_ohos_lite
49 #include "parameters.h"
50 #endif
51 #ifndef HISYSEVENT_DISABLE
52 #include "hisysevent.h"
53 #endif
54
55 namespace OHOS {
56 namespace HiviewDFX {
57 std::shared_ptr<FaultLoggerConfig> faultLoggerConfig_;
58 std::shared_ptr<FaultLoggerPipeMap> faultLoggerPipeMap_;
59
60 namespace {
61 constexpr int32_t MAX_CONNECTION = 30;
62 constexpr int32_t REQUEST_BUF_SIZE = 2048;
63 constexpr int32_t MAX_EPOLL_EVENT = 1024;
64 const int32_t FAULTLOG_FILE_PROP = 0640;
65
66 static constexpr uint32_t ROOT_UID = 0;
67 static constexpr uint32_t BMS_UID = 1000;
68 static constexpr uint32_t HIVIEW_UID = 1201;
69 static constexpr uint32_t HIDUMPER_SERVICE_UID = 1212;
70 static constexpr uint32_t FOUNDATION_UID = 5523;
71 static const std::string FAULTLOGGERD_TAG = "FaultLoggerd";
72 static const std::string DAEMON_RESP = "RESP:COMPLETE";
73 static const int DAEMON_REMOVE_FILE_TIME_S = 60;
74
GetRequestTypeName(int32_t type)75 static std::string GetRequestTypeName(int32_t type)
76 {
77 switch (type) {
78 case (int32_t)FaultLoggerType::CPP_CRASH:
79 return "cppcrash";
80 case (int32_t)FaultLoggerType::CPP_STACKTRACE: // change the name to nativestack ?
81 return "stacktrace";
82 case (int32_t)FaultLoggerType::JS_STACKTRACE:
83 return "jsstack";
84 case (int32_t)FaultLoggerType::JS_HEAP_SNAPSHOT:
85 case (int32_t)FaultLoggerType::JS_RAW_SNAPSHOT:
86 return "jsheap";
87 case (int32_t)FaultLoggerType::JS_HEAP_LEAK_LIST:
88 return "leaklist";
89 case (int32_t)FaultLoggerType::LEAK_STACKTRACE:
90 return "leakstack";
91 case (int32_t)FaultLoggerType::FFRT_CRASH_LOG:
92 return "ffrtlog";
93 case (int32_t)FaultLoggerType::JIT_CODE_LOG:
94 return "jitcode";
95 default:
96 return "unsupported";
97 }
98 }
99
CheckCallerUID(uint32_t callerUid)100 static bool CheckCallerUID(uint32_t callerUid)
101 {
102 // If caller's is BMS / root or caller's uid/pid is validate, just return true
103 if ((callerUid == BMS_UID) ||
104 (callerUid == ROOT_UID) ||
105 (callerUid == HIVIEW_UID) ||
106 (callerUid == HIDUMPER_SERVICE_UID) ||
107 (callerUid == FOUNDATION_UID)) {
108 return true;
109 }
110 DFXLOGW("%{public}s :: CheckCallerUID :: Caller Uid(%{public}d) is unexpectly.\n",
111 FAULTLOGGERD_TAG.c_str(), callerUid);
112 return false;
113 }
114 }
115
ReportExceptionToSysEvent(CrashDumpException& exception)116 static void ReportExceptionToSysEvent(CrashDumpException& exception)
117 {
118 #ifndef HISYSEVENT_DISABLE
119 std::string errMessage;
120 if (exception.error == CRASH_DUMP_LOCAL_REPORT) {
121 std::ifstream rfile;
122 if (strlen(exception.message) == 0) {
123 return;
124 }
125 rfile.open(exception.message, std::ios::binary | std::ios::ate);
126 if (!rfile.is_open()) {
127 return;
128 }
129 std::streamsize size = rfile.tellg();
130 rfile.seekg(0, std::ios::beg);
131 std::vector<char> buf(size);
132 rfile.read(buf.data(), size);
133 errMessage = std::string(buf.begin(), buf.end());
134 } else {
135 errMessage = exception.message;
136 }
137 HiSysEventWrite(
138 HiSysEvent::Domain::RELIABILITY,
139 "CPP_CRASH_EXCEPTION",
140 HiSysEvent::EventType::FAULT,
141 "PID", exception.pid,
142 "UID", exception.uid,
143 "HAPPEN_TIME", exception.time,
144 "ERROR_CODE", exception.error,
145 "ERROR_MSG", errMessage);
146 #endif
147 }
148
FaultLoggerDaemon()149 FaultLoggerDaemon::FaultLoggerDaemon()
150 {
151 #ifndef is_ohos_lite
152 isBeta_ = OHOS::system::GetParameter("const.logsystem.versiontype", "false") == "beta";
153 #endif
154 }
155
StartServer()156 int32_t FaultLoggerDaemon::StartServer()
157 {
158 if (!CreateSockets()) {
159 DFXLOGE("%{public}s :: Failed to create faultloggerd sockets.", FAULTLOGGERD_TAG.c_str());
160 CleanupSockets();
161 return -1;
162 }
163
164 if (!InitEnvironment()) {
165 DFXLOGE("%{public}s :: Failed to init environment.", FAULTLOGGERD_TAG.c_str());
166 CleanupSockets();
167 return -1;
168 }
169
170 if (!CreateEventFd()) {
171 DFXLOGE("%{public}s :: Failed to create eventFd.", FAULTLOGGERD_TAG.c_str());
172 CleanupSockets();
173 return -1;
174 }
175 RemoveTempFileIfNeed();
176 // loop in WaitForRequest
177 WaitForRequest();
178 CleanupEventFd();
179 CleanupSockets();
180 return 0;
181 }
182
HandleAccept(int32_t epollFd, int32_t socketFd)183 void FaultLoggerDaemon::HandleAccept(int32_t epollFd, int32_t socketFd)
184 {
185 DFX_TRACE_SCOPED("HandleAccept");
186 struct sockaddr_un clientAddr;
187 socklen_t clientAddrSize = static_cast<socklen_t>(sizeof(clientAddr));
188
189 int connectionFd = OHOS_TEMP_FAILURE_RETRY(accept(socketFd,
190 reinterpret_cast<struct sockaddr *>(&clientAddr), &clientAddrSize));
191 if (connectionFd < 0) {
192 DFXLOGW("%{public}s :: Failed to accept connection", FAULTLOGGERD_TAG.c_str());
193 return;
194 }
195
196 AddEvent(eventFd_, connectionFd, EPOLLIN);
197 connectionMap_[connectionFd] = socketFd;
198 }
199
200 #ifdef FAULTLOGGERD_FUZZER
HandleStaticForFuzzer(int32_t type, uint32_t callerUid)201 bool FaultLoggerDaemon::HandleStaticForFuzzer(int32_t type, uint32_t callerUid)
202 {
203 std::string str = GetRequestTypeName(type);
204 bool ret = CheckCallerUID(callerUid);
205 if (str == "unsupported" || !ret) {
206 return false;
207 } else {
208 return true;
209 }
210 }
211
HandleRequestForFuzzer(int32_t epollFd, int32_t connectionFd, const FaultLoggerdRequest *requestConst, FaultLoggerdRequest *request)212 void FaultLoggerDaemon::HandleRequestForFuzzer(int32_t epollFd, int32_t connectionFd,
213 const FaultLoggerdRequest *requestConst, FaultLoggerdRequest *request)
214 {
215 if (faultLoggerConfig_ == nullptr) {
216 faultLoggerConfig_ = std::make_shared<FaultLoggerConfig>(LOG_FILE_NUMBER, LOG_FILE_SIZE,
217 LOG_FILE_PATH, DEBUG_LOG_FILE_PATH);
218 }
219 HandleRequest(epollFd, connectionFd);
220 HandleLogFileDesClientRequest(connectionFd, requestConst);
221 HandlePrintTHilogClientRequest(connectionFd, request);
222 HandlePermissionRequest(connectionFd, request);
223 HandleSdkDumpRequest(connectionFd, request);
224 HandleExceptionRequest(connectionFd, request);
225 }
226 #endif
227
CheckReadRequest(ssize_t nread, ssize_t size)228 static bool CheckReadRequest(ssize_t nread, ssize_t size)
229 {
230 if (nread < 0) {
231 DFXLOGE("%{public}s :: Failed to read message", FAULTLOGGERD_TAG.c_str());
232 return false;
233 } else if (nread == 0) {
234 DFXLOGE("%{public}s :: Read null from request socket", FAULTLOGGERD_TAG.c_str());
235 return false;
236 } else if (nread != static_cast<long>(size)) {
237 return false;
238 }
239 return true;
240 }
241
HandleRequestByClientType(int32_t connectionFd, FaultLoggerdRequest* request)242 void FaultLoggerDaemon::HandleRequestByClientType(int32_t connectionFd, FaultLoggerdRequest* request)
243 {
244 switch (request->clientType) {
245 case static_cast<int32_t>(FaultLoggerClientType::DEFAULT_CLIENT):
246 HandleDefaultClientRequest(connectionFd, request);
247 break;
248 case static_cast<int32_t>(FaultLoggerClientType::LOG_FILE_DES_CLIENT):
249 HandleLogFileDesClientRequest(connectionFd, request);
250 break;
251 case static_cast<int32_t>(FaultLoggerClientType::PRINT_T_HILOG_CLIENT):
252 HandlePrintTHilogClientRequest(connectionFd, request);
253 break;
254 case static_cast<int32_t>(FaultLoggerClientType::PERMISSION_CLIENT):
255 HandlePermissionRequest(connectionFd, request);
256 break;
257 case static_cast<int32_t>(FaultLoggerClientType::SDK_DUMP_CLIENT):
258 HandleSdkDumpRequest(connectionFd, request);
259 break;
260 case static_cast<int32_t>(FaultLoggerClientType::PIPE_FD_CLIENT):
261 HandlePipeFdClientRequest(connectionFd, request);
262 break;
263 case static_cast<int32_t>(FaultLoggerClientType::REPORT_EXCEPTION_CLIENT):
264 HandleExceptionRequest(connectionFd, request);
265 break;
266 default:
267 DFXLOGE("%{public}s :: unknown clientType(%{public}d).\n", FAULTLOGGERD_TAG.c_str(), request->clientType);
268 break;
269 }
270 }
271
HandleRequest(int32_t epollFd, int32_t connectionFd)272 void FaultLoggerDaemon::HandleRequest(int32_t epollFd, int32_t connectionFd)
273 {
274 if (epollFd < 0 || connectionFd < 3) { // 3: not allow fd = 0,1,2 because they are reserved by system
275 DFXLOGE("%{public}s :: HandleRequest recieved invalid fd parmeters.", FAULTLOGGERD_TAG.c_str());
276 return;
277 }
278
279 std::vector<uint8_t> buf(REQUEST_BUF_SIZE, 0);
280 do {
281 ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, buf.data(), REQUEST_BUF_SIZE));
282 if (CheckReadRequest(nread, sizeof(FaultLoggerdStatsRequest))) {
283 HandleDumpStats(connectionFd, reinterpret_cast<FaultLoggerdStatsRequest *>(buf.data()));
284 break;
285 }
286 if (!CheckReadRequest(nread, sizeof(FaultLoggerdRequest))) {
287 break;
288 }
289 auto request = reinterpret_cast<FaultLoggerdRequest *>(buf.data());
290 if (!CheckRequestCredential(connectionFd, request)) {
291 break;
292 }
293 DFXLOGD("%{public}s :: clientType(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->clientType);
294 HandleRequestByClientType(connectionFd, request);
295 } while (false);
296 DelEvent(eventFd_, connectionFd, EPOLLIN);
297 connectionMap_.erase(connectionFd);
298 }
299
InitEnvironment()300 bool FaultLoggerDaemon::InitEnvironment()
301 {
302 faultLoggerConfig_ = std::make_shared<FaultLoggerConfig>(LOG_FILE_NUMBER, LOG_FILE_SIZE,
303 LOG_FILE_PATH, DEBUG_LOG_FILE_PATH);
304 faultLoggerPipeMap_ = std::make_shared<FaultLoggerPipeMap>();
305
306 if (!OHOS::ForceCreateDirectory(faultLoggerConfig_->GetLogFilePath())) {
307 DFXLOGE("%{public}s :: Failed to ForceCreateDirectory GetLogFilePath", FAULTLOGGERD_TAG.c_str());
308 return false;
309 }
310
311 signal(SIGCHLD, SIG_IGN);
312 signal(SIGPIPE, SIG_IGN);
313 return true;
314 }
315
HandleDefaultClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)316 void FaultLoggerDaemon::HandleDefaultClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)
317 {
318 DFX_TRACE_SCOPED("HandleDefaultClientRequest");
319 int fd = CreateFileForRequest(request->type, request->pid, request->tid, request->time);
320 if (fd < 0) {
321 DFXLOGE("[%{public}d]: %{public}s :: Failed to create log file, errno(%{public}d)", __LINE__,
322 FAULTLOGGERD_TAG.c_str(), errno);
323 return;
324 }
325 RecordFileCreation(request->type, request->pid);
326 SendFileDescriptorToSocket(connectionFd, fd);
327
328 close(fd);
329 }
330
HandleLogFileDesClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)331 void FaultLoggerDaemon::HandleLogFileDesClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)
332 {
333 int fd = CreateFileForRequest(request->type, request->pid, request->tid, request->time);
334 if (fd < 0) {
335 DFXLOGE("[%{public}d]: %{public}s :: Failed to create log file, errno(%{public}d)", __LINE__,
336 FAULTLOGGERD_TAG.c_str(), errno);
337 return;
338 }
339 SendFileDescriptorToSocket(connectionFd, fd);
340
341 close(fd);
342 }
343
HandleExceptionRequest(int32_t connectionFd, FaultLoggerdRequest * request)344 void FaultLoggerDaemon::HandleExceptionRequest(int32_t connectionFd, FaultLoggerdRequest * request)
345 {
346 if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd,
347 DAEMON_RESP.c_str(), DAEMON_RESP.length())) != static_cast<ssize_t>(DAEMON_RESP.length())) {
348 DFXLOGE("[%{public}d]: %{public}s :: Failed to write DAEMON_RESP.", __LINE__, FAULTLOGGERD_TAG.c_str());
349 }
350
351 CrashDumpException exception;
352 (void)memset_s(&exception, sizeof(CrashDumpException), 0, sizeof(CrashDumpException));
353 ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, &exception, sizeof(CrashDumpException)));
354 exception.message[LINE_BUF_SIZE - 1] = '\0';
355 if (!CheckReadRequest(nread, sizeof(CrashDumpException))) {
356 return;
357 }
358
359 ReportExceptionToSysEvent(exception);
360 }
361
HandleReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)362 void FaultLoggerDaemon::HandleReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
363 FaultLoggerPipe2* faultLoggerPipe)
364 {
365 FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
366 if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
367 return;
368 }
369 if ((faultLoggerPipe->faultLoggerPipeBuf_) != nullptr) {
370 fd = faultLoggerPipe->faultLoggerPipeBuf_->GetReadFd();
371 }
372 }
373
HandleWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)374 void FaultLoggerDaemon::HandleWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)
375 {
376 if ((faultLoggerPipe->faultLoggerPipeBuf_) != nullptr) {
377 fd = faultLoggerPipe->faultLoggerPipeBuf_->GetWriteFd();
378 }
379 }
380
HandleReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)381 void FaultLoggerDaemon::HandleReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
382 FaultLoggerPipe2* faultLoggerPipe)
383 {
384 FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
385 if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
386 return;
387 }
388 if ((faultLoggerPipe->faultLoggerPipeRes_) != nullptr) {
389 fd = faultLoggerPipe->faultLoggerPipeRes_->GetReadFd();
390 }
391 }
392
HandleWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)393 void FaultLoggerDaemon::HandleWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)
394 {
395 if ((faultLoggerPipe->faultLoggerPipeRes_) != nullptr) {
396 fd = faultLoggerPipe->faultLoggerPipeRes_->GetWriteFd();
397 }
398 }
399
HandleDelete(FaultLoggerdRequest* request)400 void FaultLoggerDaemon::HandleDelete(FaultLoggerdRequest* request)
401 {
402 faultLoggerPipeMap_->Del(request->pid);
403 }
404
HandleJsonReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)405 void FaultLoggerDaemon::HandleJsonReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
406 FaultLoggerPipe2* faultLoggerPipe)
407 {
408 FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
409 if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
410 return;
411 }
412 if ((faultLoggerPipe->faultLoggerJsonPipeBuf_) != nullptr) {
413 fd = faultLoggerPipe->faultLoggerJsonPipeBuf_->GetReadFd();
414 }
415 }
416
HandleJsonWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)417 void FaultLoggerDaemon::HandleJsonWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)
418 {
419 if ((faultLoggerPipe->faultLoggerJsonPipeBuf_) != nullptr) {
420 fd = faultLoggerPipe->faultLoggerJsonPipeBuf_->GetWriteFd();
421 }
422 }
423
HandleJsonReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)424 void FaultLoggerDaemon::HandleJsonReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
425 FaultLoggerPipe2* faultLoggerPipe)
426 {
427 FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
428 if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
429 return;
430 }
431 if ((faultLoggerPipe->faultLoggerJsonPipeRes_) != nullptr) {
432 fd = faultLoggerPipe->faultLoggerJsonPipeRes_->GetReadFd();
433 }
434 }
435
HandleJsonWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)436 void FaultLoggerDaemon::HandleJsonWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)
437 {
438 if ((faultLoggerPipe->faultLoggerJsonPipeRes_) != nullptr) {
439 fd = faultLoggerPipe->faultLoggerJsonPipeRes_->GetWriteFd();
440 }
441 }
442
HandleRequestByPipeType(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)443 void FaultLoggerDaemon::HandleRequestByPipeType(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
444 FaultLoggerPipe2* faultLoggerPipe)
445 {
446 switch (request->pipeType) {
447 case (int32_t)FaultLoggerPipeType::PIPE_FD_READ_BUF: {
448 HandleReadBuf(fd, connectionFd, request, faultLoggerPipe);
449 break;
450 }
451 case (int32_t)FaultLoggerPipeType::PIPE_FD_WRITE_BUF: {
452 HandleWriteBuf(fd, faultLoggerPipe);
453 break;
454 }
455 case (int32_t)FaultLoggerPipeType::PIPE_FD_READ_RES: {
456 HandleReadRes(fd, connectionFd, request, faultLoggerPipe);
457 break;
458 }
459 case (int32_t)FaultLoggerPipeType::PIPE_FD_WRITE_RES: {
460 HandleWriteRes(fd, faultLoggerPipe);
461 break;
462 }
463 case (int32_t)FaultLoggerPipeType::PIPE_FD_DELETE: {
464 HandleDelete(request);
465 return;
466 }
467 case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF: {
468 HandleJsonReadBuf(fd, connectionFd, request, faultLoggerPipe);
469 break;
470 }
471 case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_WRITE_BUF: {
472 HandleJsonWriteBuf(fd, faultLoggerPipe);
473 break;
474 }
475 case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_READ_RES: {
476 HandleJsonReadRes(fd, connectionFd, request, faultLoggerPipe);
477 break;
478 }
479 case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES: {
480 HandleJsonWriteRes(fd, faultLoggerPipe);
481 break;
482 }
483 default:
484 DFXLOGE("%{public}s :: unknown pipeType(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->pipeType);
485 return;
486 }
487 }
488
HandlePipeFdClientRequest(int32_t connectionFd, FaultLoggerdRequest * request)489 void FaultLoggerDaemon::HandlePipeFdClientRequest(int32_t connectionFd, FaultLoggerdRequest * request)
490 {
491 DFX_TRACE_SCOPED("HandlePipeFdClientRequest");
492 DFXLOGD("%{public}s :: pid(%{public}d), pipeType(%{public}d).", FAULTLOGGERD_TAG.c_str(),
493 request->pid, request->pipeType);
494 int fd = -1;
495 FaultLoggerPipe2* faultLoggerPipe = faultLoggerPipeMap_->Get(request->pid);
496 if (faultLoggerPipe == nullptr) {
497 DFXLOGE("%{public}s :: cannot find pipe fd for pid(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->pid);
498 return;
499 }
500 HandleRequestByPipeType(fd, connectionFd, request, faultLoggerPipe);
501 if (fd < 0) {
502 DFXLOGE("%{public}s :: Failed to get pipe fd, pipeType(%{public}d)",
503 FAULTLOGGERD_TAG.c_str(), request->pipeType);
504 return;
505 }
506 SendFileDescriptorToSocket(connectionFd, fd);
507 }
508
HandlePrintTHilogClientRequest(int32_t const connectionFd, FaultLoggerdRequest * request)509 void FaultLoggerDaemon::HandlePrintTHilogClientRequest(int32_t const connectionFd, FaultLoggerdRequest * request)
510 {
511 char buf[LINE_BUF_SIZE] = {0};
512
513 if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd,
514 DAEMON_RESP.c_str(), DAEMON_RESP.length())) != static_cast<ssize_t>(DAEMON_RESP.length())) {
515 DFXLOGE("[%{public}d]: %{public}s :: Failed to write DAEMON_RESP.", __LINE__, FAULTLOGGERD_TAG.c_str());
516 }
517
518 int nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, buf, sizeof(buf) - 1));
519 if (nread < 0) {
520 DFXLOGE("%{public}s :: Failed to read message, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
521 } else if (nread == 0) {
522 DFXLOGE("%{public}s :: HandlePrintTHilogClientRequest :: Read null from request socket",
523 FAULTLOGGERD_TAG.c_str());
524 } else {
525 DFXLOGE("%{public}s", buf);
526 }
527 }
528
SecurityCheck(int32_t connectionFd, FaultLoggerdRequest * request)529 FaultLoggerCheckPermissionResp FaultLoggerDaemon::SecurityCheck(int32_t connectionFd, FaultLoggerdRequest * request)
530 {
531 FaultLoggerCheckPermissionResp resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
532
533 struct ucred rcred;
534 do {
535 int optval = 1;
536 if (OHOS_TEMP_FAILURE_RETRY(setsockopt(connectionFd,
537 SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval))) == -1) {
538 DFXLOGE("%{public}s :: setsockopt SO_PASSCRED error, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
539 break;
540 }
541
542 if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd, DAEMON_RESP.c_str(), DAEMON_RESP.length())) !=
543 static_cast<ssize_t>(DAEMON_RESP.length())) {
544 DFXLOGE("%{public}s :: Failed to write DAEMON_RESP, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
545 break;
546 }
547
548 if (!RecvMsgCredFromSocket(connectionFd, &rcred)) {
549 DFXLOGE("%{public}s :: Recv msg ucred error, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
550 break;
551 }
552
553 request->uid = rcred.uid;
554 request->callerPid = static_cast<int32_t>(rcred.pid);
555
556 auto it = connectionMap_.find(connectionFd);
557 if (it == connectionMap_.end()) {
558 break;
559 }
560
561 if (it->second == sdkdumpSocketFd_) {
562 resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS;
563 break;
564 }
565
566 bool res = CheckCallerUID(request->uid);
567 if (res) {
568 resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS;
569 }
570 } while (false);
571
572 return resCheckPermission;
573 }
574
HandlePermissionRequest(int32_t connectionFd, FaultLoggerdRequest * request)575 void FaultLoggerDaemon::HandlePermissionRequest(int32_t connectionFd, FaultLoggerdRequest * request)
576 {
577 FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
578 if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS == resSecurityCheck) {
579 OHOS_TEMP_FAILURE_RETRY(send(connectionFd, "1", strlen("1"), 0));
580 }
581 if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT == resSecurityCheck) {
582 OHOS_TEMP_FAILURE_RETRY(send(connectionFd, "2", strlen("2"), 0));
583 }
584 }
585
HandleSdkDumpRequest(int32_t connectionFd, FaultLoggerdRequest * request)586 void FaultLoggerDaemon::HandleSdkDumpRequest(int32_t connectionFd, FaultLoggerdRequest * request)
587 {
588 DFX_TRACE_SCOPED("HandleSdkDumpRequest");
589 DFXLOGI("Receive dump request for pid:%{public}d tid:%{public}d.", request->pid, request->tid);
590 FaultLoggerSdkDumpResp resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_PASS;
591 FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
592
593 /*
594 * all threads my user, local pid my user, remote pid other user's process
595 * 3rd Y Y(in signal_handler local) Y(in signal_handler loacl) N
596 * system Y Y(in signal_handler local) Y(in signal_handler loacl) Y(in signal_handler remote)
597 * root Y Y(in signal_handler local) Y(in signal_handler loacl) Y(in signal_handler remote)
598 */
599
600 /*
601 * 1. pid != 0 && tid != 0: means we want dump a thread, so we send signal to a thread.
602 Main thread stack is tid's stack, we need ignore other thread info.
603 * 2. pid != 0 && tid == 0: means we want dump a process, so we send signal to process.
604 Main thead stack is pid's stack, we need other tread info.
605 */
606
607 /*
608 * in signal_handler we need to check caller pid and tid(which is send to signal handler by SYS_rt_sig.).
609 * 1. caller pid == signal pid, means we do back trace in ourself process, means local backtrace.
610 * |- we do all tid back trace in signal handler's local unwind.
611 * 2. pid != signal pid, means we do remote back trace.
612 */
613
614 /*
615 * in local back trace, all unwind stack will save to signal_handler global var.(mutex lock in signal handler.)
616 * in remote back trace, all unwind stack will save to file, and read in dump_catcher, then return.
617 */
618
619 do {
620 if ((request->pid <= 0) || (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT == resSecurityCheck)) {
621 DFXLOGE("%{public}s :: HandleSdkDumpRequest :: pid(%{public}d) or resSecurityCheck(%{public}d) fail.\n", \
622 FAULTLOGGERD_TAG.c_str(), request->pid, (int)resSecurityCheck);
623 resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_REJECT;
624 break;
625 }
626 DFXLOGI("Sdk dump pid(%{public}d) request pass permission verification.", request->pid);
627 if (IsCrashed(request->pid)) {
628 resSdkDump = FaultLoggerSdkDumpResp::SDK_PROCESS_CRASHED;
629 DFXLOGW("%{public}s :: pid(%{public}d) has been crashed, break.\n",
630 FAULTLOGGERD_TAG.c_str(), request->pid);
631 break;
632 }
633 if (faultLoggerPipeMap_->Check(request->pid, request->time)) {
634 resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_REPEAT;
635 DFXLOGE("%{public}s :: pid(%{public}d) is dumping, break.\n", FAULTLOGGERD_TAG.c_str(), request->pid);
636 break;
637 }
638 faultLoggerPipeMap_->Set(request->pid, request->time, request->isJson);
639
640 #pragma clang diagnostic push
641 #pragma clang diagnostic ignored "-Winitializer-overrides"
642 // defined in out/hi3516dv300/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/signal.h
643 siginfo_t si {0};
644 si.si_signo = SIGDUMP;
645 si.si_errno = 0;
646 si.si_value.sival_int = request->tid;
647 if (request->tid == 0 && sizeof(void *) == 8) { // 8 : platform 64
648 si.si_value.sival_ptr = reinterpret_cast<void *>(request->endTime | (1ULL << 63)); // 63 : platform 64
649 }
650 si.si_code = request->sigCode;
651 si.si_pid = request->callerPid;
652 si.si_uid = static_cast<uid_t>(request->callerTid);
653 #pragma clang diagnostic pop
654 /*
655 * means we need dump all the threads in a process
656 * --------
657 * Accroding to the linux manual, A process-directed signal may be delivered to any one of the
658 * threads that does not currently have the signal blocked.
659 */
660 if (syscall(SYS_rt_sigqueueinfo, request->pid, si.si_signo, &si) != 0) {
661 DFXLOGE("Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", si.si_signo, errno);
662 resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_NOPROC;
663 }
664 } while (false);
665 auto retMsg = std::to_string(resSdkDump);
666 if (OHOS_TEMP_FAILURE_RETRY(send(connectionFd, retMsg.data(), retMsg.length(), 0)) !=
667 static_cast<ssize_t>(retMsg.length())) {
668 DFXLOGE("Failed to send result message to client, errno(%{public}d).", errno);
669 }
670 }
671
RecordFileCreation(int32_t type, int32_t pid)672 void FaultLoggerDaemon::RecordFileCreation(int32_t type, int32_t pid)
673 {
674 if (type == static_cast<int32_t>(FaultLoggerType::CPP_CRASH)) {
675 ClearTimeOutRecords();
676 crashTimeMap_[pid] = time(nullptr);
677 }
678 }
679
ClearTimeOutRecords()680 void FaultLoggerDaemon::ClearTimeOutRecords()
681 {
682 constexpr int validTime = 8;
683 auto currentTime = time(nullptr);
684 for (auto it = crashTimeMap_.begin(); it != crashTimeMap_.end();) {
685 if ((it->second + validTime) <= currentTime) {
686 crashTimeMap_.erase(it++);
687 } else {
688 it++;
689 }
690 }
691 }
692
IsCrashed(int32_t pid)693 bool FaultLoggerDaemon::IsCrashed(int32_t pid)
694 {
695 DFX_TRACE_SCOPED("IsCrashed");
696 ClearTimeOutRecords();
697 return crashTimeMap_.find(pid) != crashTimeMap_.end();
698 }
699
CreateFileForRequest(int32_t type, int32_t pid, int32_t tid, uint64_t time) const700 int32_t FaultLoggerDaemon::CreateFileForRequest(int32_t type, int32_t pid, int32_t tid, uint64_t time) const
701 {
702 RemoveTempFileIfNeed();
703 std::string typeStr = GetRequestTypeName(type);
704 if (typeStr == "unsupported") {
705 DFXLOGE("Unsupported request type(%{public}d)", type);
706 return -1;
707 }
708
709 std::string folderPath = "";
710 folderPath = faultLoggerConfig_->GetLogFilePath();
711
712 if (time == 0) {
713 time = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>\
714 (std::chrono::system_clock::now().time_since_epoch()).count());
715 }
716
717 std::string ss = folderPath + "/" + typeStr + "-" + std::to_string(pid);
718 if (type == FaultLoggerType::JS_HEAP_SNAPSHOT || type == FaultLoggerType::JS_RAW_SNAPSHOT) {
719 ss += "-" + std::to_string(tid);
720 }
721 ss += "-" + std::to_string(time);
722 if (type == FaultLoggerType::JS_RAW_SNAPSHOT) {
723 ss += ".rawheap";
724 }
725 const std::string path = ss;
726 DFXLOGI("%{public}s :: file path(%{public}s).\n", FAULTLOGGERD_TAG.c_str(), path.c_str());
727 if (!VerifyFilePath(path, VALID_FILE_PATH)) {
728 DFXLOGE("%{public}s :: Open %{public}s fail, please check it under valid path.\n",
729 FAULTLOGGERD_TAG.c_str(), path.c_str());
730 return -1;
731 }
732 int32_t fd = OHOS_TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CREAT, FAULTLOG_FILE_PROP));
733 if (fd != -1) {
734 if (!ChangeModeFile(path, FAULTLOG_FILE_PROP)) {
735 DFXLOGE("%{public}s :: Failed to ChangeMode CreateFileForRequest", FAULTLOGGERD_TAG.c_str());
736 }
737 }
738 return fd;
739 }
740
RemoveTempFileIfNeed() const741 void FaultLoggerDaemon::RemoveTempFileIfNeed() const
742 {
743 int maxFileCount = 50;
744 int currentLogCounts = 0;
745
746 std::string logFilePath = faultLoggerConfig_->GetLogFilePath();
747 std::vector<std::string> files;
748 OHOS::GetDirFiles(logFilePath, files);
749 constexpr uint64_t maxFileSize = 1lu << 31; // 2GB
750 if (!isBeta_ && OHOS::GetFolderSize(logFilePath) > maxFileSize) {
751 DFXLOGE("%{public}s :: current file size is over limit, clear all files", FAULTLOGGERD_TAG.c_str());
752 std::for_each(files.begin(), files.end(), OHOS::RemoveFile);
753 return;
754 }
755 currentLogCounts = (int)files.size();
756 maxFileCount = faultLoggerConfig_->GetLogFileMaxNumber();
757 if (currentLogCounts < maxFileCount) {
758 return;
759 }
760
761 std::sort(files.begin(), files.end(),
762 [](const std::string& lhs, const std::string& rhs) -> int {
763 auto lhsSplitPos = lhs.find_last_of("-");
764 auto rhsSplitPos = rhs.find_last_of("-");
765 if (lhsSplitPos == std::string::npos || rhsSplitPos == std::string::npos) {
766 return lhs.compare(rhs) > 0;
767 }
768
769 return lhs.substr(lhsSplitPos).compare(rhs.substr(rhsSplitPos)) > 0;
770 });
771
772 time_t currentTime = static_cast<time_t>(time(nullptr));
773 if (currentTime <= 0) {
774 DFXLOGE("%{public}s :: currentTime is less than zero CreateFileForRequest", FAULTLOGGERD_TAG.c_str());
775 }
776
777 constexpr int deleteNum = 1;
778 int startIndex = maxFileCount > deleteNum ? maxFileCount - deleteNum : maxFileCount;
779 for (unsigned int index = (unsigned int)startIndex; index < files.size(); index++) {
780 struct stat st;
781 int err = stat(files[index].c_str(), &st);
782 if (err != 0) {
783 DFXLOGE("%{public}s :: Get log stat failed, errno(%{public}d).", FAULTLOGGERD_TAG.c_str(), errno);
784 } else {
785 if ((currentTime - st.st_mtime) <= DAEMON_REMOVE_FILE_TIME_S) {
786 continue;
787 }
788 }
789
790 OHOS::RemoveFile(files[index]);
791 DFXLOGD("%{public}s :: Now we rm file(%{public}s) as max log number exceeded.", \
792 FAULTLOGGERD_TAG.c_str(), files[index].c_str());
793 }
794 }
795
AddEvent(int32_t epollFd, int32_t addFd, uint32_t event)796 void FaultLoggerDaemon::AddEvent(int32_t epollFd, int32_t addFd, uint32_t event)
797 {
798 epoll_event ev;
799 ev.events = event;
800 ev.data.fd = addFd;
801 int ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, addFd, &ev);
802 if (ret < 0) {
803 DFXLOGW("%{public}s :: Failed to epoll ctl add Fd(%{public}d), errno(%{public}d)",
804 FAULTLOGGERD_TAG.c_str(), addFd, errno);
805 }
806 }
807
DelEvent(int32_t epollFd, int32_t delFd, uint32_t event)808 void FaultLoggerDaemon::DelEvent(int32_t epollFd, int32_t delFd, uint32_t event)
809 {
810 epoll_event ev;
811 ev.events = event;
812 ev.data.fd = delFd;
813 int ret = epoll_ctl(epollFd, EPOLL_CTL_DEL, delFd, &ev);
814 if (ret < 0) {
815 DFXLOGW("%{public}s :: Failed to epoll ctl del Fd(%{public}d), errno(%{public}d)",
816 FAULTLOGGERD_TAG.c_str(), delFd, errno);
817 }
818 close(delFd);
819 }
820
CheckRequestCredential(int32_t connectionFd, FaultLoggerdRequest* request)821 bool FaultLoggerDaemon::CheckRequestCredential(int32_t connectionFd, FaultLoggerdRequest* request)
822 {
823 if (request == nullptr) {
824 return false;
825 }
826
827 auto it = connectionMap_.find(connectionFd);
828 if (it == connectionMap_.end()) {
829 DFXLOGE("%{public}s : Failed to find fd:%{public}d, map size:%{public}zu", FAULTLOGGERD_TAG.c_str(),
830 connectionFd, connectionMap_.size());
831 return false;
832 }
833
834 if (it->second == crashSocketFd_ || it->second == sdkdumpSocketFd_) {
835 // only processdump use this socket
836 return true;
837 }
838
839 struct ucred creds = {};
840 socklen_t credSize = sizeof(creds);
841 int err = getsockopt(connectionFd, SOL_SOCKET, SO_PEERCRED, &creds, &credSize);
842 if (err != 0) {
843 DFXLOGE("%{public}s :: Failed to CheckRequestCredential, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
844 return false;
845 }
846
847 if (CheckCallerUID(creds.uid)) {
848 return true;
849 }
850
851 bool isCredentialMatched = (creds.pid == request->pid);
852 if (request->clientType == (int32_t)REPORT_EXCEPTION_CLIENT) {
853 isCredentialMatched = (creds.uid == request->uid); /* check uid when report exception */
854 }
855 if (!isCredentialMatched) {
856 DFXLOGW("Failed to check request credential request:%{public}d:" \
857 "%{public}d cred:%{public}d:%{public}d fd:%{public}d:%{public}d",
858 request->pid, request->uid, creds.pid, creds.uid, it->second, crashSocketFd_);
859 }
860 return isCredentialMatched;
861 }
862
CreateSockets()863 bool FaultLoggerDaemon::CreateSockets()
864 {
865 if (!StartListen(defaultSocketFd_, SERVER_SOCKET_NAME, MAX_CONNECTION)) {
866 return false;
867 }
868
869 if (!StartListen(crashSocketFd_, SERVER_CRASH_SOCKET_NAME, MAX_CONNECTION)) {
870 close(defaultSocketFd_);
871 defaultSocketFd_ = -1;
872 return false;
873 }
874 #ifndef is_ohos_lite
875 if (!StartListen(sdkdumpSocketFd_, SERVER_SDKDUMP_SOCKET_NAME, MAX_CONNECTION)) {
876 close(defaultSocketFd_);
877 defaultSocketFd_ = -1;
878 close(crashSocketFd_);
879 crashSocketFd_ = -1;
880 return false;
881 }
882 #endif
883 return true;
884 }
885
CleanupSockets()886 void FaultLoggerDaemon::CleanupSockets()
887 {
888 if (defaultSocketFd_ >= 0) {
889 close(defaultSocketFd_);
890 defaultSocketFd_ = -1;
891 }
892
893 if (crashSocketFd_ >= 0) {
894 close(crashSocketFd_);
895 crashSocketFd_ = -1;
896 }
897
898 if (sdkdumpSocketFd_ >= 0) {
899 close(sdkdumpSocketFd_);
900 sdkdumpSocketFd_ = -1;
901 }
902 }
903
CreateEventFd()904 bool FaultLoggerDaemon::CreateEventFd()
905 {
906 eventFd_ = epoll_create(MAX_EPOLL_EVENT);
907 if (eventFd_ < 0) {
908 return false;
909 }
910 return true;
911 }
912
WaitForRequest()913 void FaultLoggerDaemon::WaitForRequest()
914 {
915 AddEvent(eventFd_, defaultSocketFd_, EPOLLIN);
916 AddEvent(eventFd_, crashSocketFd_, EPOLLIN);
917 AddEvent(eventFd_, sdkdumpSocketFd_, EPOLLIN);
918 epoll_event events[MAX_CONNECTION];
919 DFXLOGD("%{public}s :: %{public}s: start epoll wait.", FAULTLOGGERD_TAG.c_str(), __func__);
920 do {
921 int epollNum = OHOS_TEMP_FAILURE_RETRY(epoll_wait(eventFd_, events, MAX_CONNECTION, -1));
922 if (epollNum < 0) {
923 DFXLOGE("%{public}s :: %{public}s: epoll wait error, errno(%{public}d).",
924 FAULTLOGGERD_TAG.c_str(), __func__, errno);
925 continue;
926 }
927 for (int i = 0; i < epollNum; i++) {
928 if (!(events[i].events & EPOLLIN)) {
929 DFXLOGW("%{public}s :: %{public}s: epoll event(%{public}d) error.",
930 FAULTLOGGERD_TAG.c_str(), __func__, events[i].events);
931 continue;
932 }
933
934 int fd = events[i].data.fd;
935 if (fd == defaultSocketFd_ || fd == crashSocketFd_ || fd == sdkdumpSocketFd_) {
936 HandleAccept(eventFd_, fd);
937 } else {
938 HandleRequest(eventFd_, fd);
939 }
940 }
941 } while (true);
942 }
943
CleanupEventFd()944 void FaultLoggerDaemon::CleanupEventFd()
945 {
946 DelEvent(eventFd_, defaultSocketFd_, EPOLLIN);
947 DelEvent(eventFd_, crashSocketFd_, EPOLLIN);
948 DelEvent(eventFd_, sdkdumpSocketFd_, EPOLLIN);
949
950 if (eventFd_ > 0) {
951 close(eventFd_);
952 eventFd_ = -1;
953 }
954 }
955
GetElfName(FaultLoggerdStatsRequest* request)956 std::string GetElfName(FaultLoggerdStatsRequest* request)
957 {
958 if (request == nullptr || strlen(request->callerElf) > NAME_BUF_LEN) {
959 return "";
960 }
961
962 std::string ss = StringPrintf("%s(%p)", request->callerElf, reinterpret_cast<void *>(request->offset));
963 return ss;
964 }
965
HandleDumpStats(int32_t connectionFd, FaultLoggerdStatsRequest* request)966 void FaultLoggerDaemon::HandleDumpStats(int32_t connectionFd, FaultLoggerdStatsRequest* request)
967 {
968 DFXLOGI("%{public}s :: %{public}s: HandleDumpStats", FAULTLOGGERD_TAG.c_str(), __func__);
969 size_t index = 0;
970 bool hasRecord = false;
971 for (index = 0; index < stats_.size(); index++) {
972 if (stats_[index].pid == request->pid) {
973 hasRecord = true;
974 break;
975 }
976 }
977
978 DumpStats stats;
979 if (request->type == PROCESS_DUMP && !hasRecord) {
980 stats.pid = request->pid;
981 stats.signalTime = request->signalTime;
982 stats.processdumpStartTime = request->processdumpStartTime;
983 stats.processdumpFinishTime = request->processdumpFinishTime;
984 stats.targetProcessName = request->targetProcess;
985 stats_.emplace_back(stats);
986 } else if (request->type == DUMP_CATCHER && hasRecord) {
987 stats_[index].requestTime = request->requestTime;
988 stats_[index].dumpCatcherFinishTime = request->dumpCatcherFinishTime;
989 stats_[index].callerElfName = GetElfName(request);
990 stats_[index].callerProcessName = request->callerProcess;
991 stats_[index].result = request->result;
992 stats_[index].summary = request->summary;
993 ReportDumpStats(stats_[index]);
994 stats_.erase(stats_.begin() + index);
995 } else if (request->type == DUMP_CATCHER) {
996 stats.pid = request->pid;
997 stats.requestTime = request->requestTime;
998 stats.dumpCatcherFinishTime = request->dumpCatcherFinishTime;
999 stats.callerElfName = GetElfName(request);
1000 stats.result = request->result;
1001 stats.callerProcessName = request->callerProcess;
1002 stats.summary = request->summary;
1003 stats.targetProcessName = request->targetProcess;
1004 ReportDumpStats(stats);
1005 }
1006 RemoveTimeoutDumpStats();
1007 }
1008
RemoveTimeoutDumpStats()1009 void FaultLoggerDaemon::RemoveTimeoutDumpStats()
1010 {
1011 const uint64_t timeout = 10000;
1012 uint64_t now = GetTimeMilliSeconds();
1013 for (auto it = stats_.begin(); it != stats_.end();) {
1014 if (((now > it->signalTime) && (now - it->signalTime > timeout)) ||
1015 (now <= it->signalTime)) {
1016 it = stats_.erase(it);
1017 } else {
1018 ++it;
1019 }
1020 }
1021 }
1022
ReportDumpStats(const DumpStats& stat)1023 void FaultLoggerDaemon::ReportDumpStats(const DumpStats& stat)
1024 {
1025 #ifndef HISYSEVENT_DISABLE
1026 HiSysEventWrite(
1027 HiSysEvent::Domain::HIVIEWDFX,
1028 "DUMP_CATCHER_STATS",
1029 HiSysEvent::EventType::STATISTIC,
1030 "CALLER_PROCESS_NAME", stat.callerProcessName,
1031 "CALLER_FUNC_NAME", stat.callerElfName,
1032 "TARGET_PROCESS_NAME", stat.targetProcessName,
1033 "RESULT", stat.result,
1034 "SUMMARY", stat.summary, // we need to parse summary when interface return false
1035 "PID", stat.pid,
1036 "REQUEST_TIME", stat.requestTime,
1037 "OVERALL_TIME", stat.dumpCatcherFinishTime - stat.requestTime,
1038 "SIGNAL_TIME", stat.signalTime - stat.requestTime,
1039 "DUMPER_START_TIME", stat.processdumpStartTime - stat.signalTime,
1040 "UNWIND_TIME", stat.processdumpFinishTime - stat.processdumpStartTime);
1041 #endif
1042 }
1043 } // namespace HiviewDFX
1044 } // namespace OHOS
1045