1 /*
2 * Copyright (c) 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 "hilog_collector_impl.h"
17 #include <sys/wait.h>
18 #include <unistd.h>
19 #include "hiview_logger.h"
20 #include "hilog_decorator.h"
21
22 namespace OHOS::HiviewDFX::UCollectUtil {
23 DEFINE_LOG_TAG("HilogCollector");
24
Create()25 std::shared_ptr<HilogCollector> HilogCollector::Create()
26 {
27 return std::make_shared<HilogDecorator>(std::make_shared<HilogCollectorImpl>());
28 }
29
ExecuteHilog(int32_t pid,uint32_t lineCount,int writeFd) const30 void HilogCollectorImpl::ExecuteHilog(int32_t pid, uint32_t lineCount, int writeFd) const
31 {
32 if (writeFd < 0 || dup2(writeFd, STDOUT_FILENO) == -1 || dup2(writeFd, STDERR_FILENO) == -1) {
33 HIVIEW_LOGE("dup2 writeFd fail");
34 _exit(EXIT_FAILURE);
35 }
36
37 int ret = execl("/system/bin/hilog", "hilog", "-z", std::to_string(lineCount).c_str(),
38 "-P", std::to_string(pid).c_str(), nullptr);
39 close(writeFd);
40 if (ret < 0) {
41 HIVIEW_LOGE("execl %{public}d, errno: %{public}d", ret, errno);
42 _exit(EXIT_FAILURE);
43 }
44 _exit(EXIT_SUCCESS);
45 }
46
ReadHilog(int readFd,std::string & log) const47 void HilogCollectorImpl::ReadHilog(int readFd, std::string& log) const
48 {
49 constexpr int READ_HILOG_BUFFER_SIZE = 1024;
50 while (true) {
51 char buffer[READ_HILOG_BUFFER_SIZE] = {0};
52 ssize_t nread = read(readFd, buffer, sizeof(buffer) - 1);
53 if (nread <= 0) {
54 HIVIEW_LOGI("read hilog finished");
55 break;
56 }
57 log.append(buffer);
58 }
59 close(readFd);
60 }
61
CollectLastLog(uint32_t pid,uint32_t lineNum)62 CollectResult<std::string> HilogCollectorImpl::CollectLastLog(uint32_t pid, uint32_t lineNum)
63 {
64 CollectResult<std::string> result;
65 result.retCode = UCollect::SYSTEM_ERROR;
66 int fds[2] = {-1, -1}; // 2: one read pipe, one write pipe
67 if (pipe(fds) != 0) {
68 HIVIEW_LOGE("pipe fail.");
69 return result;
70 }
71
72 int childPid = fork();
73 if (childPid < 0) {
74 HIVIEW_LOGE("fork fail.");
75 return result;
76 }
77
78 if (childPid == 0) {
79 close(fds[0]);
80 constexpr uint32_t MAX_LINE_NUM = 10000;
81 ExecuteHilog(pid, lineNum > MAX_LINE_NUM ? MAX_LINE_NUM : lineNum, fds[1]);
82 } else {
83 close(fds[1]);
84 ReadHilog(fds[0], result.data);
85 result.retCode = UCollect::SUCCESS;
86 if (waitpid(childPid, nullptr, 0) != childPid) {
87 HIVIEW_LOGE("waitpid fail, pid: %{public}d, errno: %{public}d", childPid, errno);
88 } else {
89 HIVIEW_LOGI("waitpid %{public}d success", childPid);
90 }
91 }
92 return result;
93 }
94 } // namespace OHOS::HiviewDFX::UCollectUtil