1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include "dfx_ring_buffer_wrapper.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <securec.h> 19800b99b8Sopenharmony_ci#include <unistd.h> 20800b99b8Sopenharmony_ci 21800b99b8Sopenharmony_ci#include "dfx_define.h" 22800b99b8Sopenharmony_ci#include "dfx_logger.h" 23800b99b8Sopenharmony_ci 24800b99b8Sopenharmony_cinamespace OHOS { 25800b99b8Sopenharmony_cinamespace HiviewDFX { 26800b99b8Sopenharmony_cistatic const int32_t INVALID_FD = -1; 27800b99b8Sopenharmony_cistatic const int32_t UNUSED_FD = -2; 28800b99b8Sopenharmony_ciconst int BACK_TRACE_RING_BUFFER_PRINT_WAIT_TIME_MS = 10; 29800b99b8Sopenharmony_cistd::condition_variable DfxRingBufferWrapper::printCV_; 30800b99b8Sopenharmony_cistd::mutex DfxRingBufferWrapper::printMutex_; 31800b99b8Sopenharmony_ci 32800b99b8Sopenharmony_ciDfxRingBufferWrapper &DfxRingBufferWrapper::GetInstance() 33800b99b8Sopenharmony_ci{ 34800b99b8Sopenharmony_ci static DfxRingBufferWrapper ins; 35800b99b8Sopenharmony_ci return ins; 36800b99b8Sopenharmony_ci} 37800b99b8Sopenharmony_ci 38800b99b8Sopenharmony_civoid DfxRingBufferWrapper::LoopPrintRingBuffer() 39800b99b8Sopenharmony_ci{ 40800b99b8Sopenharmony_ci if (DfxRingBufferWrapper::GetInstance().writeFunc_ == nullptr) { 41800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().writeFunc_ = DfxRingBufferWrapper::DefaultWrite; 42800b99b8Sopenharmony_ci } 43800b99b8Sopenharmony_ci 44800b99b8Sopenharmony_ci std::unique_lock<std::mutex> lck(printMutex_); 45800b99b8Sopenharmony_ci while (true) { 46800b99b8Sopenharmony_ci auto available = DfxRingBufferWrapper::GetInstance().ringBuffer_.Available(); 47800b99b8Sopenharmony_ci auto item = DfxRingBufferWrapper::GetInstance().ringBuffer_.Read(available); 48800b99b8Sopenharmony_ci 49800b99b8Sopenharmony_ci if (available != 0) { 50800b99b8Sopenharmony_ci if (item.At(0).empty()) { 51800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().ringBuffer_.Skip(item.Length()); 52800b99b8Sopenharmony_ci continue; 53800b99b8Sopenharmony_ci } 54800b99b8Sopenharmony_ci 55800b99b8Sopenharmony_ci for (unsigned int i = 0; i < item.Length(); i++) { 56800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().writeFunc_(DfxRingBufferWrapper::GetInstance().fd_, \ 57800b99b8Sopenharmony_ci item.At(i).c_str(), item.At(i).length()); 58800b99b8Sopenharmony_ci } 59800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().ringBuffer_.Skip(item.Length()); 60800b99b8Sopenharmony_ci } else { 61800b99b8Sopenharmony_ci if (DfxRingBufferWrapper::GetInstance().hasFinished_) { 62800b99b8Sopenharmony_ci DFXLOGD("%{public}s :: print finished, exit loop.\n", __func__); 63800b99b8Sopenharmony_ci break; 64800b99b8Sopenharmony_ci } 65800b99b8Sopenharmony_ci 66800b99b8Sopenharmony_ci printCV_.wait_for(lck, std::chrono::milliseconds(BACK_TRACE_RING_BUFFER_PRINT_WAIT_TIME_MS)); 67800b99b8Sopenharmony_ci } 68800b99b8Sopenharmony_ci } 69800b99b8Sopenharmony_ci} 70800b99b8Sopenharmony_ci 71800b99b8Sopenharmony_civoid DfxRingBufferWrapper::AppendMsg(const std::string& msg) 72800b99b8Sopenharmony_ci{ 73800b99b8Sopenharmony_ci if (writeFunc_ == nullptr) { 74800b99b8Sopenharmony_ci writeFunc_ = DfxRingBufferWrapper::DefaultWrite; 75800b99b8Sopenharmony_ci } 76800b99b8Sopenharmony_ci writeFunc_(fd_, msg.c_str(), msg.length()); 77800b99b8Sopenharmony_ci} 78800b99b8Sopenharmony_ci 79800b99b8Sopenharmony_ciint DfxRingBufferWrapper::AppendBuf(const char *format, ...) 80800b99b8Sopenharmony_ci{ 81800b99b8Sopenharmony_ci int ret = -1; 82800b99b8Sopenharmony_ci char buf[LINE_BUF_SIZE] = {0}; 83800b99b8Sopenharmony_ci va_list args; 84800b99b8Sopenharmony_ci va_start(args, format); 85800b99b8Sopenharmony_ci ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format, args); 86800b99b8Sopenharmony_ci va_end(args); 87800b99b8Sopenharmony_ci if (ret < 0) { 88800b99b8Sopenharmony_ci DFXLOGE("%{public}s :: vsnprintf_s failed, line: %{public}d.", __func__, __LINE__); 89800b99b8Sopenharmony_ci } 90800b99b8Sopenharmony_ci 91800b99b8Sopenharmony_ci AppendMsg(std::string(buf)); 92800b99b8Sopenharmony_ci return ret; 93800b99b8Sopenharmony_ci} 94800b99b8Sopenharmony_ci 95800b99b8Sopenharmony_cistatic std::vector<std::string> SplitDumpInfo(const std::string& dumpInfo, const std::string& sepator) 96800b99b8Sopenharmony_ci{ 97800b99b8Sopenharmony_ci std::vector<std::string> result; 98800b99b8Sopenharmony_ci if (dumpInfo.empty() || sepator.empty()) { 99800b99b8Sopenharmony_ci return result; 100800b99b8Sopenharmony_ci } 101800b99b8Sopenharmony_ci size_t begin = 0; 102800b99b8Sopenharmony_ci size_t pos = dumpInfo.find(sepator, begin); 103800b99b8Sopenharmony_ci while (pos != std::string::npos) { 104800b99b8Sopenharmony_ci result.push_back(dumpInfo.substr(begin, pos - begin)); 105800b99b8Sopenharmony_ci 106800b99b8Sopenharmony_ci begin = pos + sepator.size(); 107800b99b8Sopenharmony_ci pos = dumpInfo.find(sepator, begin); 108800b99b8Sopenharmony_ci } 109800b99b8Sopenharmony_ci if (begin < dumpInfo.size()) { 110800b99b8Sopenharmony_ci result.push_back(dumpInfo.substr(begin)); 111800b99b8Sopenharmony_ci } 112800b99b8Sopenharmony_ci return result; 113800b99b8Sopenharmony_ci} 114800b99b8Sopenharmony_ci 115800b99b8Sopenharmony_civoid DfxRingBufferWrapper::AppendBaseInfo(const std::string& info) 116800b99b8Sopenharmony_ci{ 117800b99b8Sopenharmony_ci crashBaseInfo_.emplace_back(info); 118800b99b8Sopenharmony_ci} 119800b99b8Sopenharmony_ci 120800b99b8Sopenharmony_civoid DfxRingBufferWrapper::PrintBaseInfo() 121800b99b8Sopenharmony_ci{ 122800b99b8Sopenharmony_ci if (crashBaseInfo_.empty()) { 123800b99b8Sopenharmony_ci DFXLOGE("crash base info is empty"); 124800b99b8Sopenharmony_ci } 125800b99b8Sopenharmony_ci for (const auto& item : crashBaseInfo_) { 126800b99b8Sopenharmony_ci std::vector<std::string> itemVec = SplitDumpInfo(item, "\n"); 127800b99b8Sopenharmony_ci for (size_t i = 0; i < itemVec.size(); i++) { 128800b99b8Sopenharmony_ci DFXLOGI("%{public}s", itemVec[i].c_str()); 129800b99b8Sopenharmony_ci } 130800b99b8Sopenharmony_ci } 131800b99b8Sopenharmony_ci} 132800b99b8Sopenharmony_ci 133800b99b8Sopenharmony_civoid DfxRingBufferWrapper::StartThread() 134800b99b8Sopenharmony_ci{ 135800b99b8Sopenharmony_ci hasFinished_ = false; 136800b99b8Sopenharmony_ci} 137800b99b8Sopenharmony_ci 138800b99b8Sopenharmony_civoid DfxRingBufferWrapper::StopThread() 139800b99b8Sopenharmony_ci{ 140800b99b8Sopenharmony_ci if (fd_ != INVALID_FD) { 141800b99b8Sopenharmony_ci close(fd_); 142800b99b8Sopenharmony_ci } 143800b99b8Sopenharmony_ci fd_ = INVALID_FD; 144800b99b8Sopenharmony_ci} 145800b99b8Sopenharmony_ci 146800b99b8Sopenharmony_civoid DfxRingBufferWrapper::SetWriteBufFd(int32_t fd) 147800b99b8Sopenharmony_ci{ 148800b99b8Sopenharmony_ci fd_ = fd; 149800b99b8Sopenharmony_ci if (fd_ < 0) { 150800b99b8Sopenharmony_ci DFXLOGW("%{public}s :: Failed to set fd.\n", __func__); 151800b99b8Sopenharmony_ci } 152800b99b8Sopenharmony_ci} 153800b99b8Sopenharmony_ci 154800b99b8Sopenharmony_civoid DfxRingBufferWrapper::SetWriteFunc(RingBufferWriteFunc func) 155800b99b8Sopenharmony_ci{ 156800b99b8Sopenharmony_ci writeFunc_ = func; 157800b99b8Sopenharmony_ci} 158800b99b8Sopenharmony_ci 159800b99b8Sopenharmony_ciint DfxRingBufferWrapper::DefaultWrite(int32_t fd, const char *buf, const int len) 160800b99b8Sopenharmony_ci{ 161800b99b8Sopenharmony_ci if (buf == nullptr) { 162800b99b8Sopenharmony_ci return -1; 163800b99b8Sopenharmony_ci } 164800b99b8Sopenharmony_ci WriteLog(UNUSED_FD, "%s", buf); 165800b99b8Sopenharmony_ci if (fd > 0) { 166800b99b8Sopenharmony_ci return OHOS_TEMP_FAILURE_RETRY(write(fd, buf, len)); 167800b99b8Sopenharmony_ci } 168800b99b8Sopenharmony_ci return 0; 169800b99b8Sopenharmony_ci} 170800b99b8Sopenharmony_ci} // namespace HiviewDFX 171800b99b8Sopenharmony_ci} // namespace OHOS 172