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