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