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 37namespace OHOS { 38namespace HiviewDFX { 39namespace { 40const std::string FAULTLOGGER_PIPE_TAG = "FaultLoggerPipe"; 41const int PIPE_TIMEOUT = 10000; // 10 seconds 42} 43 44FaultLoggerPipe::FaultLoggerPipe() 45{ 46 init_ = false; 47 write_ = false; 48 Init(); 49} 50 51FaultLoggerPipe::~FaultLoggerPipe() 52{ 53 Destroy(); 54} 55 56int FaultLoggerPipe::GetReadFd(void) 57{ 58 DFXLOGD("%{public}s :: pipe read fd: %{public}d", __func__, fds_[PIPE_READ]); 59 return fds_[PIPE_READ]; 60} 61 62int FaultLoggerPipe::GetWriteFd(void) 63{ 64 DFXLOGD("%{public}s :: pipe write fd: %{public}d", __func__, fds_[PIPE_WRITE]); 65 if (!write_) { 66 write_ = true; 67 return fds_[PIPE_WRITE]; 68 } 69 return -1; 70} 71 72bool FaultLoggerPipe::Init(void) 73{ 74 if (!init_) { 75 if (pipe2(fds_, O_NONBLOCK) != 0) { 76 DFXLOGE("%{public}s :: Failed to create pipe.", __func__); 77 return false; 78 } 79 DFXLOGD("%{public}s :: create pipe.", __func__); 80 } 81 init_ = true; 82 if (!SetSize(MAX_PIPE_SIZE)) { 83 DFXLOGE("%{public}s :: Failed to set pipe size.", __func__); 84 } 85 return true; 86} 87 88bool 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 102void FaultLoggerPipe::Destroy(void) 103{ 104 if (init_) { 105 DFXLOGD("%{public}s :: close pipe.", __func__); 106 Close(fds_[PIPE_READ]); 107 Close(fds_[PIPE_WRITE]); 108 } 109 init_ = false; 110} 111 112void FaultLoggerPipe::Close(int fd) const 113{ 114 if (fd > 0) { 115 syscall(SYS_close, fd); 116 } 117} 118 119FaultLoggerPipe2::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 131FaultLoggerPipe2::~FaultLoggerPipe2() 132{ 133 faultLoggerPipeBuf_.reset(); 134 faultLoggerPipeRes_.reset(); 135 faultLoggerJsonPipeBuf_.reset(); 136 faultLoggerJsonPipeRes_.reset(); 137 time_ = 0; 138} 139 140FaultLoggerPipeMap::FaultLoggerPipeMap() 141{ 142 std::lock_guard<std::mutex> lck(pipeMapsMutex_); 143 faultLoggerPipes_.clear(); 144} 145 146FaultLoggerPipeMap::~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 155void 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 164bool 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 178FaultLoggerPipe2* 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 187void 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 196bool 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