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