1/* 2 * Copyright (c) 2021-2024 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 "dfx_ring_buffer_wrapper.h" 17 18#include <securec.h> 19#include <unistd.h> 20 21#include "dfx_define.h" 22#include "dfx_logger.h" 23 24namespace OHOS { 25namespace HiviewDFX { 26static const int32_t INVALID_FD = -1; 27static const int32_t UNUSED_FD = -2; 28const int BACK_TRACE_RING_BUFFER_PRINT_WAIT_TIME_MS = 10; 29std::condition_variable DfxRingBufferWrapper::printCV_; 30std::mutex DfxRingBufferWrapper::printMutex_; 31 32DfxRingBufferWrapper &DfxRingBufferWrapper::GetInstance() 33{ 34 static DfxRingBufferWrapper ins; 35 return ins; 36} 37 38void DfxRingBufferWrapper::LoopPrintRingBuffer() 39{ 40 if (DfxRingBufferWrapper::GetInstance().writeFunc_ == nullptr) { 41 DfxRingBufferWrapper::GetInstance().writeFunc_ = DfxRingBufferWrapper::DefaultWrite; 42 } 43 44 std::unique_lock<std::mutex> lck(printMutex_); 45 while (true) { 46 auto available = DfxRingBufferWrapper::GetInstance().ringBuffer_.Available(); 47 auto item = DfxRingBufferWrapper::GetInstance().ringBuffer_.Read(available); 48 49 if (available != 0) { 50 if (item.At(0).empty()) { 51 DfxRingBufferWrapper::GetInstance().ringBuffer_.Skip(item.Length()); 52 continue; 53 } 54 55 for (unsigned int i = 0; i < item.Length(); i++) { 56 DfxRingBufferWrapper::GetInstance().writeFunc_(DfxRingBufferWrapper::GetInstance().fd_, \ 57 item.At(i).c_str(), item.At(i).length()); 58 } 59 DfxRingBufferWrapper::GetInstance().ringBuffer_.Skip(item.Length()); 60 } else { 61 if (DfxRingBufferWrapper::GetInstance().hasFinished_) { 62 DFXLOGD("%{public}s :: print finished, exit loop.\n", __func__); 63 break; 64 } 65 66 printCV_.wait_for(lck, std::chrono::milliseconds(BACK_TRACE_RING_BUFFER_PRINT_WAIT_TIME_MS)); 67 } 68 } 69} 70 71void DfxRingBufferWrapper::AppendMsg(const std::string& msg) 72{ 73 if (writeFunc_ == nullptr) { 74 writeFunc_ = DfxRingBufferWrapper::DefaultWrite; 75 } 76 writeFunc_(fd_, msg.c_str(), msg.length()); 77} 78 79int DfxRingBufferWrapper::AppendBuf(const char *format, ...) 80{ 81 int ret = -1; 82 char buf[LINE_BUF_SIZE] = {0}; 83 va_list args; 84 va_start(args, format); 85 ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format, args); 86 va_end(args); 87 if (ret < 0) { 88 DFXLOGE("%{public}s :: vsnprintf_s failed, line: %{public}d.", __func__, __LINE__); 89 } 90 91 AppendMsg(std::string(buf)); 92 return ret; 93} 94 95static std::vector<std::string> SplitDumpInfo(const std::string& dumpInfo, const std::string& sepator) 96{ 97 std::vector<std::string> result; 98 if (dumpInfo.empty() || sepator.empty()) { 99 return result; 100 } 101 size_t begin = 0; 102 size_t pos = dumpInfo.find(sepator, begin); 103 while (pos != std::string::npos) { 104 result.push_back(dumpInfo.substr(begin, pos - begin)); 105 106 begin = pos + sepator.size(); 107 pos = dumpInfo.find(sepator, begin); 108 } 109 if (begin < dumpInfo.size()) { 110 result.push_back(dumpInfo.substr(begin)); 111 } 112 return result; 113} 114 115void DfxRingBufferWrapper::AppendBaseInfo(const std::string& info) 116{ 117 crashBaseInfo_.emplace_back(info); 118} 119 120void DfxRingBufferWrapper::PrintBaseInfo() 121{ 122 if (crashBaseInfo_.empty()) { 123 DFXLOGE("crash base info is empty"); 124 } 125 for (const auto& item : crashBaseInfo_) { 126 std::vector<std::string> itemVec = SplitDumpInfo(item, "\n"); 127 for (size_t i = 0; i < itemVec.size(); i++) { 128 DFXLOGI("%{public}s", itemVec[i].c_str()); 129 } 130 } 131} 132 133void DfxRingBufferWrapper::StartThread() 134{ 135 hasFinished_ = false; 136} 137 138void DfxRingBufferWrapper::StopThread() 139{ 140 if (fd_ != INVALID_FD) { 141 close(fd_); 142 } 143 fd_ = INVALID_FD; 144} 145 146void DfxRingBufferWrapper::SetWriteBufFd(int32_t fd) 147{ 148 fd_ = fd; 149 if (fd_ < 0) { 150 DFXLOGW("%{public}s :: Failed to set fd.\n", __func__); 151 } 152} 153 154void DfxRingBufferWrapper::SetWriteFunc(RingBufferWriteFunc func) 155{ 156 writeFunc_ = func; 157} 158 159int DfxRingBufferWrapper::DefaultWrite(int32_t fd, const char *buf, const int len) 160{ 161 if (buf == nullptr) { 162 return -1; 163 } 164 WriteLog(UNUSED_FD, "%s", buf); 165 if (fd > 0) { 166 return OHOS_TEMP_FAILURE_RETRY(write(fd, buf, len)); 167 } 168 return 0; 169} 170} // namespace HiviewDFX 171} // namespace OHOS 172