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
FaultLoggerPipe()39 FaultLoggerPipe::FaultLoggerPipe()
40 {
41 int fds[PIPE_NUM_SZ] = {-1, -1};
42 if (pipe2(fds, O_NONBLOCK) != 0) {
43 DFXLOGE("%{public}s :: Failed to create pipe, errno: %{public}d.", __func__, errno);
44 return;
45 }
46 DFXLOGD("%{public}s :: create pipe.", __func__);
47 readFd_ = fds[PIPE_READ];
48 writeFd_ = fds[PIPE_WRITE];
49 if (fcntl(readFd_, F_SETPIPE_SZ, MAX_PIPE_SIZE) < 0 || fcntl(writeFd_, F_SETPIPE_SZ, MAX_PIPE_SIZE) < 0) {
50 DFXLOGE("%{public}s :: Failed to set pipe size, errno: %{public}d.", __func__, errno);
51 }
52 }
53
~FaultLoggerPipe()54 FaultLoggerPipe::~FaultLoggerPipe()
55 {
56 DFXLOGD("%{public}s :: close pipe.", __func__);
57 Close(readFd_);
58 Close(writeFd_);
59 }
60
FaultLoggerPipe(FaultLoggerPipe && rhs)61 FaultLoggerPipe::FaultLoggerPipe(FaultLoggerPipe&& rhs) noexcept: write_(rhs.write_),
62 readFd_(rhs.readFd_), writeFd_(rhs.writeFd_)
63 {
64 rhs.readFd_ = -1;
65 rhs.writeFd_ = -1;
66 }
67
operator =(FaultLoggerPipe && rhs)68 FaultLoggerPipe& FaultLoggerPipe::operator=(FaultLoggerPipe&& rhs) noexcept
69 {
70 if (this != &rhs) {
71 Close(readFd_);
72 Close(writeFd_);
73 readFd_ = rhs.readFd_;
74 writeFd_ = rhs.writeFd_;
75 write_ = rhs.write_;
76 rhs.readFd_ = -1;
77 rhs.writeFd_ = -1;
78 }
79 return *this;
80 }
81
GetReadFd() const82 int FaultLoggerPipe::GetReadFd() const
83 {
84 DFXLOGD("%{public}s :: pipe read fd: %{public}d", __func__, readFd_);
85 return readFd_;
86 }
87
GetWriteFd()88 int FaultLoggerPipe::GetWriteFd()
89 {
90 DFXLOGD("%{public}s :: pipe write fd: %{public}d", __func__, writeFd_);
91 if (!write_) {
92 write_ = true;
93 return writeFd_;
94 }
95 return -1;
96 }
97
Close(int & fd)98 void FaultLoggerPipe::Close(int& fd)
99 {
100 if (fd > 0) {
101 syscall(SYS_close, fd);
102 fd = -1;
103 }
104 }
105
106 std::list<FaultLoggerPipePair> FaultLoggerPipePair::sdkDumpPipes_{};
107
FaultLoggerPipePair(int32_t pid,uint64_t requestTime)108 FaultLoggerPipePair::FaultLoggerPipePair(int32_t pid, uint64_t requestTime) : pid_(pid), requestTime_(requestTime) {}
109
IsValid(uint64_t checkTime) const110 bool FaultLoggerPipePair::IsValid(uint64_t checkTime) const
111 {
112 constexpr int pipeTimeOut = 10000; // 10s
113 return checkTime <= requestTime_ + pipeTimeOut;
114 }
115
GetPipeFd(PipeFdUsage usage,FaultLoggerPipeType pipeType)116 int32_t FaultLoggerPipePair::GetPipeFd(PipeFdUsage usage, FaultLoggerPipeType pipeType)
117 {
118 FaultLoggerPipe& targetPipe = (usage == PipeFdUsage::BUFFER_FD) ? faultLoggerPipeBuf_ : faultLoggerPipeRes_;
119 if (pipeType == FaultLoggerPipeType::PIPE_FD_READ) {
120 return targetPipe.GetReadFd();
121 }
122 if (pipeType == FaultLoggerPipeType::PIPE_FD_WRITE) {
123 return targetPipe.GetWriteFd();
124 }
125 return -1;
126 }
127
CreateSdkDumpPipePair(int pid,uint64_t requestTime)128 FaultLoggerPipePair& FaultLoggerPipePair::CreateSdkDumpPipePair(int pid, uint64_t requestTime)
129 {
130 auto pipePair = GetSdkDumpPipePair(pid);
131 if (pipePair != nullptr) {
132 return *pipePair;
133 }
134 return sdkDumpPipes_.emplace_back(pid, requestTime);
135 }
136
CheckSdkDumpRecord(int pid,uint64_t checkTime)137 bool FaultLoggerPipePair::CheckSdkDumpRecord(int pid, uint64_t checkTime)
138 {
139 auto iter = std::find_if(sdkDumpPipes_.begin(), sdkDumpPipes_.end(),
140 [pid](const FaultLoggerPipePair& faultLoggerPipePair) {
141 return faultLoggerPipePair.pid_ == pid;
142 });
143 if (iter != sdkDumpPipes_.end()) {
144 if (iter->IsValid(checkTime)) {
145 return true;
146 }
147 sdkDumpPipes_.erase(iter);
148 }
149 return false;
150 }
151
GetSdkDumpPipePair(int pid)152 FaultLoggerPipePair* FaultLoggerPipePair::GetSdkDumpPipePair(int pid)
153 {
154 auto iter = std::find_if(sdkDumpPipes_.begin(), sdkDumpPipes_.end(),
155 [pid](const FaultLoggerPipePair& faultLoggerPipePair) {
156 return faultLoggerPipePair.pid_ == pid;
157 });
158 return iter == sdkDumpPipes_.end() ? nullptr : &(*iter);
159 }
160
DelSdkDumpPipePair(int pid)161 void FaultLoggerPipePair::DelSdkDumpPipePair(int pid)
162 {
163 sdkDumpPipes_.remove_if([pid](const FaultLoggerPipePair& faultLoggerPipePair) {
164 return faultLoggerPipePair.pid_ == pid;
165 });
166 }
167 } // namespace HiviewDfx
168 } // namespace OHOS
169