• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "log_kmsg.h"
17 #include <cstdlib>
18 #include <cinttypes>
19 #include <iostream>
20 #include <string>
21 #include <thread>
22 #include <fstream>
23 #include <sys/klog.h>
24 #include <sys/syslog.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/prctl.h>
30 #include <init_file.h>
31 #include <hilog/log.h>
32 #include <log_utils.h>
33 
34 namespace OHOS {
35 namespace HiviewDFX {
36 using namespace std;
37 
GetInstance(HilogBuffer & hilogBuffer)38 LogKmsg& LogKmsg::GetInstance(HilogBuffer& hilogBuffer)
39 {
40     static LogKmsg logKmsg(hilogBuffer);
41     return logKmsg;
42 }
43 
LinuxReadOneKmsg(KmsgParser & parser)44 ssize_t LogKmsg::LinuxReadOneKmsg(KmsgParser& parser)
45 {
46     std::vector<char> kmsgBuffer(BUFSIZ, '\0');
47     ssize_t size = -1;
48     do {
49         size = read(kmsgCtl, kmsgBuffer.data(), BUFSIZ - 1);
50     } while (size < 0 && errno == EPIPE);
51     if (size > 0) {
52         std::optional<HilogMsgWrapper> msgWrap = parser.ParseKmsg(kmsgBuffer);
53         if (msgWrap.has_value()) {
54             size_t result = hilogBuffer.Insert(msgWrap->GetHilogMsg());
55             if (result <= 0) {
56                 return result;
57             }
58         }
59     }
60     return size;
61 }
62 
LinuxReadAllKmsg()63 int LogKmsg::LinuxReadAllKmsg()
64 {
65     ssize_t rdFailTimes = 0;
66     const ssize_t maxFailTime = 10;
67     kmsgCtl = GetControlFile("/dev/kmsg");
68     if (kmsgCtl < 0) {
69         std::cout << "Cannot open kmsg! ";
70         PrintErrorno(errno);
71         return -1;
72     }
73     std::unique_ptr<KmsgParser> parser = std::make_unique<KmsgParser>();
74     if (parser == nullptr) {
75         return -1;
76     }
77     while (true) {
78         if (threadStatus == STOP) {
79             break;
80         }
81         ssize_t sz = LinuxReadOneKmsg(*parser);
82         if (sz < 0) {
83             rdFailTimes++;
84             if (maxFailTime < rdFailTimes) {
85                 std::cout << "Read kmsg failed more than maxFailTime" << std::endl;
86                 return -1;
87             }
88             sleep(1);
89             continue;
90         }
91         rdFailTimes = 0;
92     }
93     return 1;
94 }
95 
ReadAllKmsg()96 void LogKmsg::ReadAllKmsg()
97 {
98     prctl(PR_SET_NAME, "hilogd.rd_kmsg");
99 #ifdef __linux__
100     std::cout << "Platform: Linux" << std::endl;
101     LinuxReadAllKmsg();
102 #endif
103 }
104 
Start()105 void LogKmsg::Start()
106 {
107     std::lock_guard<decltype(startMtx)> lock(startMtx);
108     if (threadStatus == NONEXIST || threadStatus == STOP) {
109         logKmsgThread = std::thread ([this]() {
110             ReadAllKmsg();
111         });
112     } else {
113         std::cout << " Thread already started!\n";
114     }
115     threadStatus = START;
116 }
117 
Stop()118 void LogKmsg::Stop()
119 {
120     if (threadStatus == NONEXIST || threadStatus == STOP) {
121         std::cout << "Thread was exited or not started!\n";
122         return;
123     }
124     threadStatus = STOP;
125     if (logKmsgThread.joinable()) {
126         logKmsgThread.join();
127     }
128 }
129 
~LogKmsg()130 LogKmsg::~LogKmsg()
131 {
132     close(kmsgCtl);
133 }
134 } // namespace HiviewDFX
135 } // namespace OHOS
136