1 /*
2 * Copyright (c) 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_service.h"
17
18 #include <algorithm>
19 #include <fstream>
20 #include <sys/wait.h>
21 #include <sys/socket.h>
22 #include <sys/syscall.h>
23 #include "dfx_define.h"
24 #include "dfx_log.h"
25 #include "dfx_lperf.h"
26 #include "dfx_trace.h"
27 #include "dfx_util.h"
28 #include "fault_logger_daemon.h"
29 #include "faultloggerd_socket.h"
30 #include "fault_common_util.h"
31 #include "procinfo.h"
32 #include "proc_util.h"
33
34 #ifndef is_ohos_lite
35 #include "fault_logger_pipe.h"
36 #endif
37
38 #ifndef HISYSEVENT_DISABLE
39 #include "hisysevent.h"
40 #endif
41
42 #include "string_printf.h"
43 #include "temp_file_manager.h"
44
45 namespace OHOS {
46 namespace HiviewDFX {
47
48 namespace {
49 constexpr const char* const FAULTLOGGERD_SERVICE_TAG = "FAULT_LOGGER_SERVICE";
CheckCallerUID(uint32_t callerUid)50 bool CheckCallerUID(uint32_t callerUid)
51 {
52 const uint32_t whitelist[] = {
53 0, // rootUid
54 1000, // bmsUid
55 1201, // hiviewUid
56 1212, // hidumperServiceUid
57 5523, // foundationUid
58 };
59 if (std::find(std::begin(whitelist), std::end(whitelist), callerUid) == std::end(whitelist)) {
60 DFXLOGW("%{public}s :: CheckCallerUID :: Caller Uid(%{public}d) is unexpectly.",
61 FAULTLOGGERD_SERVICE_TAG, callerUid);
62 return false;
63 }
64 return true;
65 }
66
CheckRequestCredential(int32_t connectionFd,int32_t requestPid)67 bool CheckRequestCredential(int32_t connectionFd, int32_t requestPid)
68 {
69 struct ucred creds{};
70 if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd)) {
71 return false;
72 }
73 if (CheckCallerUID(creds.uid)) {
74 return true;
75 }
76 if (creds.pid != requestPid) {
77 DFXLOGW("Failed to check request credential request:%{public}d: cred:%{public}d fd:%{public}d",
78 requestPid, creds.pid, connectionFd);
79 return false;
80 }
81 return true;
82 }
83 }
84
85 #ifndef HISYSEVENT_DISABLE
Filter(int32_t connectionFd,const CrashDumpException & requestData)86 bool ExceptionReportService::Filter(int32_t connectionFd, const CrashDumpException& requestData)
87 {
88 if (strlen(requestData.message) == 0) {
89 return false;
90 }
91 struct ucred creds{};
92 if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd) ||
93 creds.uid != static_cast<uint32_t>(requestData.uid)) {
94 DFXLOGW("Failed to check request credential request uid:%{public}d: cred uid:%{public}d fd:%{public}d",
95 requestData.uid, creds.uid, connectionFd);
96 return false;
97 }
98 return true;
99 }
100
OnRequest(const std::string & socketName,int32_t connectionFd,const CrashDumpException & requestData)101 int32_t ExceptionReportService::OnRequest(const std::string& socketName, int32_t connectionFd,
102 const CrashDumpException& requestData)
103 {
104 if (!Filter(connectionFd, requestData)) {
105 return ResponseCode::REQUEST_REJECT;
106 }
107 HiSysEventWrite(
108 HiSysEvent::Domain::RELIABILITY,
109 "CPP_CRASH_EXCEPTION",
110 HiSysEvent::EventType::FAULT,
111 "PID", requestData.pid,
112 "UID", requestData.uid,
113 "HAPPEN_TIME", requestData.time,
114 "ERROR_CODE", requestData.error,
115 "ERROR_MSG", requestData.message);
116 #ifdef FAULTLOGGERD_TEST
117 int32_t responseData = ResponseCode::REQUEST_SUCCESS;
118 SendMsgToSocket(connectionFd, &responseData, sizeof(responseData));
119 #endif
120 return ResponseCode::REQUEST_SUCCESS;
121 }
122
RemoveTimeoutDumpStats()123 void StatsService::RemoveTimeoutDumpStats()
124 {
125 constexpr uint64_t timeout = 10000; // 10s
126 uint64_t now = GetTimeMilliSeconds();
127 stats_.remove_if([&now, &timeout](const auto& stats) {
128 return (now > stats.signalTime && now - stats.signalTime > timeout) ||
129 now <= stats.signalTime;
130 });
131 }
132
ReportDumpStats(const DumpStats & stat)133 void StatsService::ReportDumpStats(const DumpStats& stat)
134 {
135 HiSysEventWrite(
136 HiSysEvent::Domain::HIVIEWDFX,
137 "DUMP_CATCHER_STATS",
138 HiSysEvent::EventType::STATISTIC,
139 "CALLER_PROCESS_NAME", stat.callerProcessName,
140 "CALLER_FUNC_NAME", stat.callerElfName,
141 "TARGET_PROCESS_NAME", stat.targetProcessName,
142 "RESULT", stat.result,
143 "SUMMARY", stat.summary, // we need to parse summary when interface return false
144 "PID", stat.pid,
145 "REQUEST_TIME", stat.requestTime,
146 "OVERALL_TIME", stat.dumpCatcherFinishTime - stat.requestTime,
147 "SIGNAL_TIME", stat.signalTime - stat.requestTime,
148 "DUMPER_START_TIME", stat.processdumpStartTime - stat.signalTime,
149 "WRITE_DUMP_INFO_TIME", stat.writeDumpInfoCost,
150 "UNWIND_TIME", stat.processdumpFinishTime - stat.processdumpStartTime,
151 "TARGET_PROCESS_THREAD_COUNT", stat.targetProcessThreadCount);
152 }
153
GetElfName(const FaultLoggerdStatsRequest & request)154 std::string StatsService::GetElfName(const FaultLoggerdStatsRequest& request)
155 {
156 if (strlen(request.callerElf) > NAME_BUF_LEN) {
157 return "";
158 }
159 return StringPrintf("%s(%p)", request.callerElf, reinterpret_cast<void*>(request.offset));
160 }
161
OnRequest(const std::string & socketName,int32_t connectionFd,const FaultLoggerdStatsRequest & requestData)162 int32_t StatsService::OnRequest(const std::string& socketName, int32_t connectionFd,
163 const FaultLoggerdStatsRequest& requestData)
164 {
165 constexpr int32_t delayTime = 7; // allow 10s for processdump report, 3s for dumpcatch timeout and 7s for delay
166 DFXLOGI("%{public}s :: %{public}s: HandleDumpStats", FAULTLOGGERD_SERVICE_TAG, __func__);
167 auto iter = std::find_if(stats_.begin(), stats_.end(), [&requestData](const DumpStats& dumpStats) {
168 return dumpStats.pid == requestData.pid;
169 });
170 if (requestData.type == PROCESS_DUMP && iter == stats_.end()) {
171 auto& stats = stats_.emplace_back();
172 stats.pid = requestData.pid;
173 stats.signalTime = requestData.signalTime;
174 stats.processdumpStartTime = requestData.processdumpStartTime;
175 stats.processdumpFinishTime = requestData.processdumpFinishTime;
176 stats.targetProcessName = requestData.targetProcess;
177 stats.writeDumpInfoCost = requestData.writeDumpInfoCost;
178 } else if (requestData.type == DUMP_CATCHER) {
179 auto task = [requestData, this] {
180 auto iter = std::find_if(stats_.begin(), stats_.end(), [&requestData](const DumpStats& dumpStats) {
181 return dumpStats.pid == requestData.pid;
182 });
183 DumpStats stats;
184 if (iter != stats_.end()) {
185 stats = *iter;
186 stats_.erase(iter);
187 }
188 stats.pid = requestData.pid;
189 stats.requestTime = requestData.requestTime;
190 stats.dumpCatcherFinishTime = requestData.dumpCatcherFinishTime;
191 stats.callerElfName = GetElfName(requestData);
192 stats.result = requestData.result;
193 stats.callerProcessName = requestData.callerProcess;
194 stats.summary = requestData.summary;
195 stats.targetProcessName = requestData.targetProcess;
196 stats.targetProcessThreadCount = requestData.targetProcessThreadCount;
197 ReportDumpStats(stats);
198 RemoveTimeoutDumpStats();
199 };
200 StartDelayTask(task, delayTime);
201 }
202 RemoveTimeoutDumpStats();
203 #ifdef FAULTLOGGERD_TEST
204 int32_t responseData = ResponseCode::REQUEST_SUCCESS;
205 SendMsgToSocket(connectionFd, &responseData, sizeof(responseData));
206 #endif
207 return ResponseCode::REQUEST_SUCCESS;
208 }
209
StartDelayTask(std::function<void ()> workFunc,int32_t delayTime)210 void StatsService::StartDelayTask(std::function<void()> workFunc, int32_t delayTime)
211 {
212 auto delayTask = DelayTask::CreateInstance(workFunc, delayTime);
213 FaultLoggerDaemon::GetEpollManager(EpollManagerType::MAIN_SERVER).AddListener(std::move(delayTask));
214 }
215 #endif
216
OnRequest(const std::string & socketName,int32_t connectionFd,const FaultLoggerdRequest & requestData)217 int32_t FileDesService::OnRequest(const std::string& socketName, int32_t connectionFd,
218 const FaultLoggerdRequest& requestData)
219 {
220 DFX_TRACE_SCOPED("FileDesServiceOnRequest");
221 if (!Filter(socketName, connectionFd, requestData)) {
222 return ResponseCode::REQUEST_REJECT;
223 }
224 SmartFd fileFd(TempFileManager::CreateFileDescriptor(requestData.type, requestData.pid,
225 requestData.tid, requestData.time));
226 if (!fileFd) {
227 return ResponseCode::ABNORMAL_SERVICE;
228 }
229 #ifndef is_ohos_lite
230 TempFileManager::RecordFileCreation(requestData.type, requestData.pid);
231 #endif
232 int32_t responseData = ResponseCode::REQUEST_SUCCESS;
233 SendMsgToSocket(connectionFd, &responseData, sizeof(responseData));
234 int fd = fileFd.GetFd();
235 SendFileDescriptorToSocket(connectionFd, &fd, 1);
236 return responseData;
237 }
238
Filter(const std::string & socketName,int32_t connectionFd,const FaultLoggerdRequest & requestData)239 bool FileDesService::Filter(const std::string& socketName, int32_t connectionFd,
240 const FaultLoggerdRequest& requestData)
241 {
242 switch (requestData.type) {
243 case FaultLoggerType::CPP_CRASH:
244 case FaultLoggerType::CPP_STACKTRACE:
245 case FaultLoggerType::LEAK_STACKTRACE:
246 case FaultLoggerType::JIT_CODE_LOG:
247 return socketName == SERVER_CRASH_SOCKET_NAME;
248 default:
249 return CheckRequestCredential(connectionFd, requestData.pid);
250 }
251 }
252
253 #ifndef is_ohos_lite
Filter(const std::string & socketName,const SdkDumpRequestData & requestData,uint32_t uid)254 int32_t SdkDumpService::Filter(const std::string& socketName, const SdkDumpRequestData& requestData, uint32_t uid)
255 {
256 if (requestData.pid <= 0 || socketName != SERVER_SDKDUMP_SOCKET_NAME || !CheckCallerUID(uid)) {
257 DFXLOGE("%{public}s :: HandleSdkDumpRequest :: pid(%{public}d) or socketName(%{public}s) fail.",
258 FAULTLOGGERD_SERVICE_TAG, requestData.pid, socketName.c_str());
259 return ResponseCode::REQUEST_REJECT;
260 }
261 if (TempFileManager::CheckCrashFileRecord(requestData.pid)) {
262 DFXLOGW("%{public}s :: pid(%{public}d) has been crashed, break.",
263 FAULTLOGGERD_SERVICE_TAG, requestData.pid);
264 return ResponseCode::SDK_PROCESS_CRASHED;
265 }
266 if (FaultLoggerPipePair::CheckSdkDumpRecord(requestData.pid, requestData.time)) {
267 DFXLOGE("%{public}s :: pid(%{public}d) is dumping, break.", FAULTLOGGERD_SERVICE_TAG, requestData.pid);
268 return ResponseCode::SDK_DUMP_REPEAT;
269 }
270 return ResponseCode::REQUEST_SUCCESS;
271 }
272
OnRequest(const std::string & socketName,int32_t connectionFd,const SdkDumpRequestData & requestData)273 int32_t SdkDumpService::OnRequest(const std::string& socketName, int32_t connectionFd,
274 const SdkDumpRequestData& requestData)
275 {
276 DFX_TRACE_SCOPED("SdkDumpServiceOnRequest");
277 DFXLOGI("Receive dump request for pid:%{public}d tid:%{public}d.", requestData.pid, requestData.tid);
278 struct ucred creds;
279 if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd)) {
280 return ResponseCode::REQUEST_REJECT;
281 }
282 int32_t responseCode = Filter(socketName, requestData, creds.uid);
283 if (responseCode != ResponseCode::REQUEST_SUCCESS) {
284 return responseCode;
285 }
286
287 /*
288 * all threads my user, local pid my user, remote pid other user's process
289 * 3rd Y Y(in signal_handler local) Y(in signal_handler loacl) N
290 * system Y Y(in signal_handler local) Y(in signal_handler loacl) Y(in signal_handler remote)
291 * root Y Y(in signal_handler local) Y(in signal_handler loacl) Y(in signal_handler remote)
292 */
293
294 /*
295 * 1. pid != 0 && tid != 0: means we want dump a thread, so we send signal to a thread.
296 Main thread stack is tid's stack, we need ignore other thread info.
297 * 2. pid != 0 && tid == 0: means we want dump a process, so we send signal to process.
298 Main thead stack is pid's stack, we need other tread info.
299 */
300
301 /*
302 * in signal_handler we need to check caller pid and tid(which is send to signal handler by SYS_rt_sig.).
303 * 1. caller pid == signal pid, means we do back trace in ourself process, means local backtrace.
304 * |- we do all tid back trace in signal handler's local unwind.
305 * 2. pid != signal pid, means we do remote back trace.
306 */
307
308 /*
309 * in local back trace, all unwind stack will save to signal_handler global var.(mutex lock in signal handler.)
310 * in remote back trace, all unwind stack will save to file, and read in dump_catcher, then return.
311 */
312
313 #pragma clang diagnostic push
314 #pragma clang diagnostic ignored "-Winitializer-overrides"
315 // defined in out/hi3516dv300/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/signal.h
316 siginfo_t si{0};
317 si.si_signo = SIGDUMP;
318 si.si_errno = 0;
319 si.si_value.sival_int = requestData.tid;
320 if (requestData.tid == 0 && sizeof(void*) == 8) { // 8 : platform 64
321 si.si_value.sival_ptr = reinterpret_cast<void*>(requestData.endTime | (1ULL << 63)); // 63 : platform 64
322 }
323 si.si_code = requestData.sigCode;
324 si.si_pid = static_cast<int32_t>(creds.pid);
325 si.si_uid = static_cast<uid_t>(requestData.callerTid);
326 #pragma clang diagnostic pop
327 /*
328 * means we need dump all the threads in a process
329 * --------
330 * Accroding to the linux manual, A process-directed signal may be delivered to any one of the
331 * threads that does not currently have the signal blocked.
332 */
333 auto& faultLoggerPipe = FaultLoggerPipePair::CreateSdkDumpPipePair(requestData.pid, requestData.time);
334
335 if (auto ret = FaultCommonUtil::SendSignalToProcess(requestData.pid, si); ret != ResponseCode::REQUEST_SUCCESS) {
336 FaultLoggerPipePair::DelSdkDumpPipePair(requestData.pid);
337 return ret;
338 }
339
340 int32_t fds[PIPE_NUM_SZ] = {
341 faultLoggerPipe.GetPipeFd(PipeFdUsage::BUFFER_FD, FaultLoggerPipeType::PIPE_FD_READ),
342 faultLoggerPipe.GetPipeFd(PipeFdUsage::RESULT_FD, FaultLoggerPipeType::PIPE_FD_READ)
343 };
344 if (fds[PIPE_BUF_INDEX] < 0 || fds[PIPE_RES_INDEX] < 0) {
345 return ResponseCode::ABNORMAL_SERVICE;
346 }
347 int32_t res = ResponseCode::REQUEST_SUCCESS;
348 SendMsgToSocket(connectionFd, &res, sizeof(res));
349 SendFileDescriptorToSocket(connectionFd, fds, PIPE_NUM_SZ);
350 return res;
351 }
352
Filter(const std::string & socketName,int32_t connectionFd,const PipFdRequestData & requestData)353 bool PipeService::Filter(const std::string &socketName, int32_t connectionFd, const PipFdRequestData &requestData)
354 {
355 if (requestData.pipeType > FaultLoggerPipeType::PIPE_FD_DELETE ||
356 requestData.pipeType < FaultLoggerPipeType::PIPE_FD_READ) {
357 return false;
358 }
359 if (socketName == SERVER_CRASH_SOCKET_NAME) {
360 return true;
361 }
362 return CheckRequestCredential(connectionFd, requestData.pid);
363 }
364
OnRequest(const std::string & socketName,int32_t connectionFd,const PipFdRequestData & requestData)365 int32_t PipeService::OnRequest(const std::string& socketName, int32_t connectionFd, const PipFdRequestData& requestData)
366 {
367 DFX_TRACE_SCOPED("PipeServiceOnRequest");
368 if (!Filter(socketName, connectionFd, requestData)) {
369 return ResponseCode::REQUEST_REJECT;
370 }
371 int32_t responseData = ResponseCode::REQUEST_SUCCESS;
372 if (requestData.pipeType == FaultLoggerPipeType::PIPE_FD_DELETE) {
373 FaultLoggerPipePair::DelSdkDumpPipePair(requestData.pid);
374 SendMsgToSocket(connectionFd, &responseData, sizeof(responseData));
375 return responseData;
376 }
377 FaultLoggerPipePair* faultLoggerPipe = FaultLoggerPipePair::GetSdkDumpPipePair(requestData.pid);
378 if (faultLoggerPipe == nullptr) {
379 DFXLOGE("%{public}s :: cannot find pipe fd for pid(%{public}d).", FAULTLOGGERD_SERVICE_TAG, requestData.pid);
380 return ResponseCode::ABNORMAL_SERVICE;
381 }
382 int32_t fds[PIPE_NUM_SZ] = {
383 faultLoggerPipe->GetPipeFd(PipeFdUsage::BUFFER_FD, FaultLoggerPipeType::PIPE_FD_WRITE),
384 faultLoggerPipe->GetPipeFd(PipeFdUsage::RESULT_FD, FaultLoggerPipeType::PIPE_FD_WRITE)
385 };
386 if (fds[PIPE_BUF_INDEX] < 0 || fds[PIPE_RES_INDEX] < 0) {
387 DFXLOGE("%{public}s :: failed to get fds for pipeType(%{public}d).", FAULTLOGGERD_SERVICE_TAG,
388 requestData.pipeType);
389 return ResponseCode::ABNORMAL_SERVICE;
390 }
391 SendMsgToSocket(connectionFd, &responseData, sizeof(responseData));
392 SendFileDescriptorToSocket(connectionFd, fds, PIPE_NUM_SZ);
393 return responseData;
394 }
395
Filter(const std::string & socketName,int32_t connectionFd,const LitePerfFdRequestData & requestData)396 bool LitePerfPipeService::Filter(const std::string &socketName, int32_t connectionFd,
397 const LitePerfFdRequestData &requestData)
398 {
399 if (requestData.pipeType > FaultLoggerPipeType::PIPE_FD_DELETE ||
400 requestData.pipeType < FaultLoggerPipeType::PIPE_FD_READ) {
401 return false;
402 }
403
404 struct ucred creds{};
405 if (!FaultCommonUtil::GetUcredByPeerCred(creds, connectionFd)) {
406 return false;
407 }
408 if (creds.uid != requestData.uid) {
409 DFXLOGW("Failed to check request credential request:%{public}d, cred:%{public}d, fd:%{public}d",
410 requestData.uid, creds.uid, connectionFd);
411 return false;
412 }
413 return true;
414 }
415
OnRequest(const std::string & socketName,int32_t connectionFd,const LitePerfFdRequestData & requestData)416 int32_t LitePerfPipeService::OnRequest(const std::string& socketName, int32_t connectionFd,
417 const LitePerfFdRequestData& requestData)
418 {
419 DFX_TRACE_SCOPED("LitePerfPipeServiceOnRequest");
420 if (!Filter(socketName, connectionFd, requestData)) {
421 return ResponseCode::REQUEST_REJECT;
422 }
423 int uid = static_cast<int>(requestData.uid);
424 int32_t responseData = ResponseCode::REQUEST_SUCCESS;
425 if (requestData.pipeType == FaultLoggerPipeType::PIPE_FD_DELETE) {
426 LitePerfPipePair::DelPipePair(uid);
427 SendMsgToSocket(connectionFd, &responseData, sizeof(responseData));
428 return responseData;
429 }
430
431 int32_t fds[PIPE_NUM_SZ] = {0};
432 if (requestData.pipeType == FaultLoggerPipeType::PIPE_FD_READ) {
433 if (LitePerfPipePair::CheckDumpMax() || LitePerfPipePair::CheckDumpRecord(uid)) {
434 DFXLOGE("%{public}s :: uid(%{public}d) is dumping.", FAULTLOGGERD_SERVICE_TAG, uid);
435 return ResponseCode::SDK_DUMP_REPEAT;
436 }
437 auto& pipePair = LitePerfPipePair::CreatePipePair(uid);
438 fds[PIPE_BUF_INDEX] = pipePair.GetPipeFd(PipeFdUsage::BUFFER_FD, FaultLoggerPipeType::PIPE_FD_READ);
439 fds[PIPE_RES_INDEX] = pipePair.GetPipeFd(PipeFdUsage::RESULT_FD, FaultLoggerPipeType::PIPE_FD_READ);
440
441 constexpr int maxPerfTimeout = (MAX_STOP_SECONDS + DUMP_LITEPERF_TIMEOUT) / 1000;
442 int32_t delayTime = std::min(requestData.timeout, maxPerfTimeout);
443 auto task = [uid, this] {
444 LitePerfPipePair::DelPipePair(uid);
445 };
446 StartDelayTask(task, delayTime);
447 } else if (requestData.pipeType == FaultLoggerPipeType::PIPE_FD_WRITE) {
448 LitePerfPipePair* pipePair = LitePerfPipePair::GetPipePair(uid);
449 if (pipePair == nullptr) {
450 DFXLOGE("%{public}s :: cannot find pipe fd for pid(%{public}d).",
451 FAULTLOGGERD_SERVICE_TAG, requestData.pid);
452 return ResponseCode::ABNORMAL_SERVICE;
453 }
454 fds[PIPE_BUF_INDEX] = pipePair->GetPipeFd(PipeFdUsage::BUFFER_FD, FaultLoggerPipeType::PIPE_FD_WRITE);
455 fds[PIPE_RES_INDEX] = pipePair->GetPipeFd(PipeFdUsage::RESULT_FD, FaultLoggerPipeType::PIPE_FD_WRITE);
456 }
457 if (fds[PIPE_BUF_INDEX] < 0 || fds[PIPE_RES_INDEX] < 0) {
458 DFXLOGE("%{public}s :: failed to get fds for pipeType(%{public}d).", FAULTLOGGERD_SERVICE_TAG,
459 requestData.pipeType);
460 return ResponseCode::ABNORMAL_SERVICE;
461 }
462 SendMsgToSocket(connectionFd, &responseData, sizeof(responseData));
463 SendFileDescriptorToSocket(connectionFd, fds, PIPE_NUM_SZ);
464 return responseData;
465 }
466
StartDelayTask(std::function<void ()> workFunc,int32_t delayTime)467 void LitePerfPipeService::StartDelayTask(std::function<void()> workFunc, int32_t delayTime)
468 {
469 auto delayTask = DelayTask::CreateInstance(workFunc, delayTime);
470 FaultLoggerDaemon::GetEpollManager(EpollManagerType::MAIN_SERVER).AddListener(std::move(delayTask));
471 }
472 #endif
473 }
474 }