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