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
24 namespace OHOS {
25 namespace HiviewDFX {
26 static const int32_t INVALID_FD = -1;
27 static const int32_t UNUSED_FD = -2;
28 std::condition_variable DfxRingBufferWrapper::printCV_;
29 std::mutex DfxRingBufferWrapper::printMutex_;
30
GetInstance()31 DfxRingBufferWrapper &DfxRingBufferWrapper::GetInstance()
32 {
33 static DfxRingBufferWrapper ins;
34 return ins;
35 }
36
AppendMsg(const std::string & msg)37 void DfxRingBufferWrapper::AppendMsg(const std::string& msg)
38 {
39 if (writeFunc_ == nullptr) {
40 writeFunc_ = DfxRingBufferWrapper::DefaultWrite;
41 }
42 writeFunc_(fd_, msg.c_str(), msg.length());
43 }
44
AppendBuf(const char * format,...)45 int DfxRingBufferWrapper::AppendBuf(const char *format, ...)
46 {
47 int ret = -1;
48 char buf[LINE_BUF_SIZE] = {0};
49 va_list args;
50 va_start(args, format);
51 ret = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format, args);
52 va_end(args);
53 if (ret < 0) {
54 DFXLOGE("%{public}s :: vsnprintf_s failed, line: %{public}d.", __func__, __LINE__);
55 }
56
57 AppendMsg(std::string(buf));
58 return ret;
59 }
60
SplitDumpInfo(const std::string & dumpInfo,const std::string & sepator)61 static std::vector<std::string> SplitDumpInfo(const std::string& dumpInfo, const std::string& sepator)
62 {
63 std::vector<std::string> result;
64 if (dumpInfo.empty() || sepator.empty()) {
65 return result;
66 }
67 size_t begin = 0;
68 size_t pos = dumpInfo.find(sepator, begin);
69 while (pos != std::string::npos) {
70 result.push_back(dumpInfo.substr(begin, pos - begin));
71
72 begin = pos + sepator.size();
73 pos = dumpInfo.find(sepator, begin);
74 }
75 if (begin < dumpInfo.size()) {
76 result.push_back(dumpInfo.substr(begin));
77 }
78 return result;
79 }
80
AppendBaseInfo(const std::string & info)81 void DfxRingBufferWrapper::AppendBaseInfo(const std::string& info)
82 {
83 crashBaseInfo_.emplace_back(info);
84 }
85
PrintBaseInfo()86 void DfxRingBufferWrapper::PrintBaseInfo()
87 {
88 if (crashBaseInfo_.empty()) {
89 DFXLOGE("crash base info is empty");
90 }
91 for (const auto& item : crashBaseInfo_) {
92 std::vector<std::string> itemVec = SplitDumpInfo(item, "\n");
93 for (size_t i = 0; i < itemVec.size(); i++) {
94 DFXLOGI("%{public}s", itemVec[i].c_str());
95 }
96 }
97 }
98
StartThread()99 void DfxRingBufferWrapper::StartThread()
100 {
101 hasFinished_ = false;
102 }
103
StopThread()104 void DfxRingBufferWrapper::StopThread()
105 {
106 if (fd_ != INVALID_FD) {
107 if (fsync(fd_) == -1) {
108 DFXLOGW("Failed to fsync fd.");
109 }
110 close(fd_);
111 }
112 fd_ = INVALID_FD;
113 }
114
SetWriteBufFd(int32_t fd)115 void DfxRingBufferWrapper::SetWriteBufFd(int32_t fd)
116 {
117 fd_ = fd;
118 if (fd_ < 0) {
119 DFXLOGW("%{public}s :: Failed to set fd.\n", __func__);
120 }
121 }
122
SetWriteFunc(RingBufferWriteFunc func)123 void DfxRingBufferWrapper::SetWriteFunc(RingBufferWriteFunc func)
124 {
125 writeFunc_ = func;
126 }
127
DefaultWrite(int32_t fd,const char * buf,const int len)128 int DfxRingBufferWrapper::DefaultWrite(int32_t fd, const char *buf, const int len)
129 {
130 if (buf == nullptr) {
131 return -1;
132 }
133 WriteLog(UNUSED_FD, "%s", buf);
134 if (fd > 0) {
135 return OHOS_TEMP_FAILURE_RETRY(write(fd, buf, len));
136 }
137 return 0;
138 }
139 } // namespace HiviewDFX
140 } // namespace OHOS
141