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