1 /*
2 * Copyright (c) 2021-2023 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_pipe.h"
17
18 #include <algorithm>
19 #include <cerrno>
20 #include <ctime>
21 #include <string>
22
23 #include <fcntl.h>
24 #include <securec.h>
25 #include <unistd.h>
26
27 #include <sys/socket.h>
28 #include <sys/stat.h>
29 #include <sys/syscall.h>
30 #include <sys/types.h>
31 #include <sys/un.h>
32
33 #include "dfx_define.h"
34 #include "dfx_log.h"
35
36 namespace OHOS {
37 namespace HiviewDFX {
38 namespace {
39 constexpr size_t MAX_LITE_PERF_PIPE_SIZE = 100;
40 }
41
FaultLoggerPipe()42 FaultLoggerPipe::FaultLoggerPipe()
43 {
44 int fds[PIPE_NUM_SZ] = {-1, -1};
45 if (pipe2(fds, O_NONBLOCK) != 0) {
46 DFXLOGE("%{public}s :: Failed to create pipe, errno: %{public}d.", __func__, errno);
47 return;
48 }
49 DFXLOGD("%{public}s :: create pipe.", __func__);
50 readFd_ = SmartFd{fds[PIPE_READ]};
51 writeFd_ = SmartFd{fds[PIPE_WRITE]};
52
53 if (fcntl(readFd_.GetFd(), F_SETPIPE_SZ, MAX_PIPE_SIZE) < 0 ||
54 fcntl(writeFd_.GetFd(), F_SETPIPE_SZ, MAX_PIPE_SIZE) < 0) {
55 DFXLOGE("%{public}s :: Failed to set pipe size, errno: %{public}d.", __func__, errno);
56 }
57 }
58
GetReadFd() const59 int FaultLoggerPipe::GetReadFd() const
60 {
61 DFXLOGD("%{public}s :: pipe read fd: %{public}d", __func__, readFd_);
62 return readFd_.GetFd();
63 }
64
GetWriteFd()65 int FaultLoggerPipe::GetWriteFd()
66 {
67 DFXLOGD("%{public}s :: pipe write fd: %{public}d", __func__, writeFd_);
68 if (!write_) {
69 write_ = true;
70 return writeFd_.GetFd();
71 }
72 return -1;
73 }
74
75 std::list<FaultLoggerPipePair> FaultLoggerPipePair::sdkDumpPipes_{};
76 std::list<LitePerfPipePair> LitePerfPipePair::pipes_{};
77
FaultLoggerPipePair(int32_t pid,uint64_t requestTime)78 FaultLoggerPipePair::FaultLoggerPipePair(int32_t pid, uint64_t requestTime) : pid_(pid), requestTime_(requestTime) {}
79
IsValid(uint64_t checkTime) const80 bool FaultLoggerPipePair::IsValid(uint64_t checkTime) const
81 {
82 constexpr int pipeTimeOut = 10000; // 10s
83 return checkTime <= requestTime_ + pipeTimeOut;
84 }
85
GetPipeFd(PipeFdUsage usage,FaultLoggerPipeType pipeType)86 int32_t FaultLoggerPipePair::GetPipeFd(PipeFdUsage usage, FaultLoggerPipeType pipeType)
87 {
88 FaultLoggerPipe& targetPipe = (usage == PipeFdUsage::BUFFER_FD) ? faultLoggerPipeBuf_ : faultLoggerPipeRes_;
89 if (pipeType == FaultLoggerPipeType::PIPE_FD_READ) {
90 return targetPipe.GetReadFd();
91 }
92 if (pipeType == FaultLoggerPipeType::PIPE_FD_WRITE) {
93 return targetPipe.GetWriteFd();
94 }
95 return -1;
96 }
97
CreateSdkDumpPipePair(int pid,uint64_t requestTime)98 FaultLoggerPipePair& FaultLoggerPipePair::CreateSdkDumpPipePair(int pid, uint64_t requestTime)
99 {
100 auto pipePair = GetSdkDumpPipePair(pid);
101 if (pipePair != nullptr) {
102 return *pipePair;
103 }
104 return sdkDumpPipes_.emplace_back(pid, requestTime);
105 }
106
CheckSdkDumpRecord(int pid,uint64_t checkTime)107 bool FaultLoggerPipePair::CheckSdkDumpRecord(int pid, uint64_t checkTime)
108 {
109 auto iter = std::find_if(sdkDumpPipes_.begin(), sdkDumpPipes_.end(),
110 [pid](const FaultLoggerPipePair& faultLoggerPipePair) {
111 return faultLoggerPipePair.pid_ == pid;
112 });
113 if (iter != sdkDumpPipes_.end()) {
114 if (iter->IsValid(checkTime)) {
115 return true;
116 }
117 sdkDumpPipes_.erase(iter);
118 }
119 return false;
120 }
121
GetSdkDumpPipePair(int pid)122 FaultLoggerPipePair* FaultLoggerPipePair::GetSdkDumpPipePair(int pid)
123 {
124 auto iter = std::find_if(sdkDumpPipes_.begin(), sdkDumpPipes_.end(),
125 [pid](const FaultLoggerPipePair& faultLoggerPipePair) {
126 return faultLoggerPipePair.pid_ == pid;
127 });
128 return iter == sdkDumpPipes_.end() ? nullptr : &(*iter);
129 }
130
DelSdkDumpPipePair(int pid)131 void FaultLoggerPipePair::DelSdkDumpPipePair(int pid)
132 {
133 sdkDumpPipes_.remove_if([pid](const FaultLoggerPipePair& faultLoggerPipePair) {
134 return faultLoggerPipePair.pid_ == pid;
135 });
136 }
137
LitePerfPipePair(int32_t uid)138 LitePerfPipePair::LitePerfPipePair(int32_t uid) : uid_(uid) {}
139
GetPipeFd(PipeFdUsage usage,FaultLoggerPipeType pipeType)140 int32_t LitePerfPipePair::GetPipeFd(PipeFdUsage usage, FaultLoggerPipeType pipeType)
141 {
142 FaultLoggerPipe& targetPipe = (usage == PipeFdUsage::BUFFER_FD) ? faultLoggerPipeBuf_ : faultLoggerPipeRes_;
143 if (pipeType == FaultLoggerPipeType::PIPE_FD_READ) {
144 return targetPipe.GetReadFd();
145 }
146 if (pipeType == FaultLoggerPipeType::PIPE_FD_WRITE) {
147 return targetPipe.GetWriteFd();
148 }
149 return -1;
150 }
151
CreatePipePair(int uid)152 LitePerfPipePair& LitePerfPipePair::CreatePipePair(int uid)
153 {
154 auto pipePair = GetPipePair(uid);
155 if (pipePair != nullptr) {
156 return *pipePair;
157 }
158 return pipes_.emplace_back(uid);
159 }
160
CheckDumpMax()161 bool LitePerfPipePair::CheckDumpMax()
162 {
163 if (pipes_.size() > MAX_LITE_PERF_PIPE_SIZE) {
164 return true;
165 }
166 return false;
167 }
168
CheckDumpRecord(int uid)169 bool LitePerfPipePair::CheckDumpRecord(int uid)
170 {
171 auto iter = std::find_if(pipes_.begin(), pipes_.end(),
172 [uid](const LitePerfPipePair& pipePair) {
173 return pipePair.uid_ == uid;
174 });
175 return iter != pipes_.end();
176 }
177
GetPipePair(int uid)178 LitePerfPipePair* LitePerfPipePair::GetPipePair(int uid)
179 {
180 auto iter = std::find_if(pipes_.begin(), pipes_.end(),
181 [uid](const LitePerfPipePair& pipePair) {
182 return pipePair.uid_ == uid;
183 });
184 return iter == pipes_.end() ? nullptr : &(*iter);
185 }
186
DelPipePair(int uid)187 void LitePerfPipePair::DelPipePair(int uid)
188 {
189 pipes_.remove_if([uid](const LitePerfPipePair& pipePair) {
190 return pipePair.uid_ == uid;
191 });
192 }
193 } // namespace HiviewDfx
194 } // namespace OHOS
195