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