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 <cstdio>
21 #include <cstdlib>
22 #include <cstring>
23 #include <ctime>
24 #include <fcntl.h>
25 #include <securec.h>
26 #include <string>
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 #include <unistd.h>
33 #include <vector>
34 #include "dfx_define.h"
35 #include "dfx_log.h"
36
37
38 namespace OHOS {
39 namespace HiviewDFX {
40 namespace {
41 static const std::string FAULTLOGGER_PIPE_TAG = "FaultLoggerPipe";
42 const int PIPE_READ = 0;
43 const int PIPE_WRITE = 1;
44 const int PIPE_TIMEOUT = 10000; // 10 seconds
45 }
46
FaultLoggerPipe()47 FaultLoggerPipe::FaultLoggerPipe()
48 {
49 init_ = false;
50 write_ = false;
51 Init();
52 }
53
~FaultLoggerPipe()54 FaultLoggerPipe::~FaultLoggerPipe()
55 {
56 Destroy();
57 }
58
GetReadFd(void)59 int FaultLoggerPipe::GetReadFd(void)
60 {
61 DFXLOG_DEBUG("%s :: pipe read fd: %d", __func__, fds_[PIPE_READ]);
62 return fds_[PIPE_READ];
63 }
64
GetWriteFd(void)65 int FaultLoggerPipe::GetWriteFd(void)
66 {
67 DFXLOG_DEBUG("%s :: pipe write fd: %d", __func__, fds_[PIPE_WRITE]);
68 if (!write_) {
69 write_ = true;
70 return fds_[PIPE_WRITE];
71 }
72 return -1;
73 }
74
Init(void)75 bool FaultLoggerPipe::Init(void)
76 {
77 if (!init_) {
78 if (pipe(fds_) != 0) {
79 DFXLOG_ERROR("%s :: Failed to create pipe.", __func__);
80 return false;
81 }
82 DFXLOG_DEBUG("%s :: create pipe.", __func__);
83 }
84 init_ = true;
85 if (!SetSize(MAX_PIPE_SIZE)) {
86 DFXLOG_ERROR("%s :: Failed to set pipe size.", __func__);
87 }
88 return true;
89 }
90
SetSize(long sz)91 bool FaultLoggerPipe::SetSize(long sz)
92 {
93 if (!init_) {
94 return false;
95 }
96 if (fcntl(fds_[PIPE_READ], F_SETPIPE_SZ, sz) < 0) {
97 return false;
98 }
99 if (fcntl(fds_[PIPE_WRITE], F_SETPIPE_SZ, sz) < 0) {
100 return false;
101 }
102 return true;
103 }
104
Destroy(void)105 void FaultLoggerPipe::Destroy(void)
106 {
107 if (init_) {
108 DFXLOG_DEBUG("%s :: close pipe.", __func__);
109 Close(fds_[PIPE_READ]);
110 Close(fds_[PIPE_WRITE]);
111 }
112 init_ = false;
113 }
114
Close(int fd) const115 void FaultLoggerPipe::Close(int fd) const
116 {
117 if (fd > 0) {
118 syscall(SYS_close, fd);
119 }
120 }
121
FaultLoggerPipe2(uint64_t time,bool isJson)122 FaultLoggerPipe2::FaultLoggerPipe2(uint64_t time, bool isJson)
123 {
124 if (isJson) {
125 faultLoggerJsonPipeBuf_ = std::unique_ptr<FaultLoggerPipe>(new FaultLoggerPipe());
126 faultLoggerJsonPipeRes_ = std::unique_ptr<FaultLoggerPipe>(new FaultLoggerPipe());
127 } else {
128 faultLoggerPipeBuf_ = std::unique_ptr<FaultLoggerPipe>(new FaultLoggerPipe());
129 faultLoggerPipeRes_ = std::unique_ptr<FaultLoggerPipe>(new FaultLoggerPipe());
130 }
131 time_ = time;
132 }
133
~FaultLoggerPipe2()134 FaultLoggerPipe2::~FaultLoggerPipe2()
135 {
136 faultLoggerPipeBuf_.reset();
137 faultLoggerPipeRes_.reset();
138 faultLoggerJsonPipeBuf_.reset();
139 faultLoggerJsonPipeRes_.reset();
140 time_ = 0;
141 }
142
FaultLoggerPipeMap()143 FaultLoggerPipeMap::FaultLoggerPipeMap()
144 {
145 std::lock_guard<std::mutex> lck(pipeMapsMutex_);
146 faultLoggerPipes_.clear();
147 }
148
~FaultLoggerPipeMap()149 FaultLoggerPipeMap::~FaultLoggerPipeMap()
150 {
151 std::lock_guard<std::mutex> lck(pipeMapsMutex_);
152 std::map<int, std::unique_ptr<FaultLoggerPipe2> >::iterator iter = faultLoggerPipes_.begin();
153 while (iter != faultLoggerPipes_.end()) {
154 faultLoggerPipes_.erase(iter++);
155 }
156 }
157
Set(int pid,uint64_t time,bool isJson)158 void FaultLoggerPipeMap::Set(int pid, uint64_t time, bool isJson)
159 {
160 std::lock_guard<std::mutex> lck(pipeMapsMutex_);
161 if (!Find(pid)) {
162 std::unique_ptr<FaultLoggerPipe2> ptr = std::unique_ptr<FaultLoggerPipe2>(new FaultLoggerPipe2(time, isJson));
163 faultLoggerPipes_.emplace(pid, std::move(ptr));
164 }
165 }
166
Check(int pid,uint64_t time)167 bool FaultLoggerPipeMap::Check(int pid, uint64_t time)
168 {
169 std::lock_guard<std::mutex> lck(pipeMapsMutex_);
170 std::map<int, std::unique_ptr<FaultLoggerPipe2> >::const_iterator iter = faultLoggerPipes_.find(pid);
171 if (iter != faultLoggerPipes_.end()) {
172 if ((time > faultLoggerPipes_[pid]->time_) && (time - faultLoggerPipes_[pid]->time_) > PIPE_TIMEOUT) {
173 faultLoggerPipes_.erase(iter);
174 return false;
175 }
176 return true;
177 }
178 return false;
179 }
180
Get(int pid)181 FaultLoggerPipe2* FaultLoggerPipeMap::Get(int pid)
182 {
183 std::lock_guard<std::mutex> lck(pipeMapsMutex_);
184 if (!Find(pid)) {
185 return nullptr;
186 }
187 return faultLoggerPipes_[pid].get();
188 }
189
Del(int pid)190 void FaultLoggerPipeMap::Del(int pid)
191 {
192 std::lock_guard<std::mutex> lck(pipeMapsMutex_);
193 std::map<int, std::unique_ptr<FaultLoggerPipe2> >::const_iterator iter = faultLoggerPipes_.find(pid);
194 if (iter != faultLoggerPipes_.end()) {
195 faultLoggerPipes_.erase(iter);
196 }
197 }
198
Find(int pid) const199 bool FaultLoggerPipeMap::Find(int pid) const
200 {
201 std::map<int, std::unique_ptr<FaultLoggerPipe2> >::const_iterator iter = faultLoggerPipes_.find(pid);
202 if (iter != faultLoggerPipes_.end()) {
203 return true;
204 }
205 return false;
206 }
207 } // namespace HiviewDfx
208 } // namespace OHOS
209