12498b56bSopenharmony_ci/* 22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 42498b56bSopenharmony_ci * you may not use this file except in compliance with the License. 52498b56bSopenharmony_ci * You may obtain a copy of the License at 62498b56bSopenharmony_ci * 72498b56bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 82498b56bSopenharmony_ci * 92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 122498b56bSopenharmony_ci * See the License for the specific language governing permissions and 132498b56bSopenharmony_ci * limitations under the License. 142498b56bSopenharmony_ci */ 152498b56bSopenharmony_ci 162498b56bSopenharmony_ci#include "log_kmsg.h" 172498b56bSopenharmony_ci#include <cstdlib> 182498b56bSopenharmony_ci#include <cinttypes> 192498b56bSopenharmony_ci#include <iostream> 202498b56bSopenharmony_ci#include <string> 212498b56bSopenharmony_ci#include <thread> 222498b56bSopenharmony_ci#include <fstream> 232498b56bSopenharmony_ci#include <sys/klog.h> 242498b56bSopenharmony_ci#include <sys/syslog.h> 252498b56bSopenharmony_ci#include <unistd.h> 262498b56bSopenharmony_ci#include <fcntl.h> 272498b56bSopenharmony_ci#include <sys/types.h> 282498b56bSopenharmony_ci#include <sys/stat.h> 292498b56bSopenharmony_ci#include <sys/prctl.h> 302498b56bSopenharmony_ci#include <init_file.h> 312498b56bSopenharmony_ci#include <hilog/log.h> 322498b56bSopenharmony_ci#include <log_utils.h> 332498b56bSopenharmony_ci 342498b56bSopenharmony_cinamespace OHOS { 352498b56bSopenharmony_cinamespace HiviewDFX { 362498b56bSopenharmony_ciusing namespace std; 372498b56bSopenharmony_ci 382498b56bSopenharmony_ciconstexpr int OPEN_KMSG_TIME = 3000; // 3s 392498b56bSopenharmony_ciconstexpr int RETRY_WAIT = 10; // 10us 402498b56bSopenharmony_ciconst char* PROC_KMSG = "/proc/kmsg"; 412498b56bSopenharmony_ciconst char* DEV_KMSG = "/dev/kmsg"; 422498b56bSopenharmony_ci 432498b56bSopenharmony_ciLogKmsg& LogKmsg::GetInstance(HilogBuffer& hilogBuffer) 442498b56bSopenharmony_ci{ 452498b56bSopenharmony_ci static LogKmsg logKmsg(hilogBuffer); 462498b56bSopenharmony_ci return logKmsg; 472498b56bSopenharmony_ci} 482498b56bSopenharmony_ci 492498b56bSopenharmony_cissize_t LogKmsg::LinuxReadOneKmsg(KmsgParser& parser) 502498b56bSopenharmony_ci{ 512498b56bSopenharmony_ci std::vector<char> kmsgBuffer(BUFSIZ, '\0'); 522498b56bSopenharmony_ci ssize_t size = -1; 532498b56bSopenharmony_ci do { 542498b56bSopenharmony_ci size = read(kmsgCtl, kmsgBuffer.data(), BUFSIZ - 1); 552498b56bSopenharmony_ci } while (size < 0 && errno == EPIPE); 562498b56bSopenharmony_ci if (size > 0) { 572498b56bSopenharmony_ci std::optional<HilogMsgWrapper> msgWrap = parser.ParseKmsg(kmsgBuffer); 582498b56bSopenharmony_ci if (msgWrap.has_value()) { 592498b56bSopenharmony_ci bool isFull = false; 602498b56bSopenharmony_ci hilogBuffer.Insert(msgWrap->GetHilogMsg(), isFull); 612498b56bSopenharmony_ci while (isFull) { 622498b56bSopenharmony_ci usleep(RETRY_WAIT); 632498b56bSopenharmony_ci hilogBuffer.Insert(msgWrap->GetHilogMsg(), isFull); 642498b56bSopenharmony_ci } 652498b56bSopenharmony_ci } 662498b56bSopenharmony_ci } 672498b56bSopenharmony_ci return size; 682498b56bSopenharmony_ci} 692498b56bSopenharmony_ci 702498b56bSopenharmony_ciint LogKmsg::LinuxReadAllKmsg() 712498b56bSopenharmony_ci{ 722498b56bSopenharmony_ci ssize_t rdFailTimes = 0; 732498b56bSopenharmony_ci const ssize_t maxFailTime = 10; 742498b56bSopenharmony_ci if (access(PROC_KMSG, R_OK) != 0) { 752498b56bSopenharmony_ci this->kmsgCtl = GetControlFile(DEV_KMSG); 762498b56bSopenharmony_ci if (this->kmsgCtl < 0) { 772498b56bSopenharmony_ci return RET_FAIL; 782498b56bSopenharmony_ci } 792498b56bSopenharmony_ci } else { 802498b56bSopenharmony_ci int ret = WaitingToDo(OPEN_KMSG_TIME, PROC_KMSG, [this] (const string &path) { 812498b56bSopenharmony_ci this->kmsgCtl = open(path.c_str(), O_RDONLY); 822498b56bSopenharmony_ci if (this->kmsgCtl < 0) { 832498b56bSopenharmony_ci std::cout << "Cannot open kmsg " << this->kmsgCtl << std::endl; 842498b56bSopenharmony_ci return RET_FAIL; 852498b56bSopenharmony_ci } 862498b56bSopenharmony_ci return RET_SUCCESS; 872498b56bSopenharmony_ci }); 882498b56bSopenharmony_ci if (ret != RET_SUCCESS) { 892498b56bSopenharmony_ci return RET_FAIL; 902498b56bSopenharmony_ci } 912498b56bSopenharmony_ci } 922498b56bSopenharmony_ci 932498b56bSopenharmony_ci std::cout << "Open kmsg success." << std::endl; 942498b56bSopenharmony_ci std::unique_ptr<KmsgParser> parser = std::make_unique<KmsgParser>(); 952498b56bSopenharmony_ci if (parser == nullptr) { 962498b56bSopenharmony_ci return -1; 972498b56bSopenharmony_ci } 982498b56bSopenharmony_ci while (true) { 992498b56bSopenharmony_ci if (threadStatus == STOP) { 1002498b56bSopenharmony_ci break; 1012498b56bSopenharmony_ci } 1022498b56bSopenharmony_ci ssize_t sz = LinuxReadOneKmsg(*parser); 1032498b56bSopenharmony_ci if (sz < 0) { 1042498b56bSopenharmony_ci rdFailTimes++; 1052498b56bSopenharmony_ci if (maxFailTime < rdFailTimes) { 1062498b56bSopenharmony_ci std::cout << "Read kmsg failed more than maxFailTime" << std::endl; 1072498b56bSopenharmony_ci return -1; 1082498b56bSopenharmony_ci } 1092498b56bSopenharmony_ci sleep(1); 1102498b56bSopenharmony_ci continue; 1112498b56bSopenharmony_ci } 1122498b56bSopenharmony_ci rdFailTimes = 0; 1132498b56bSopenharmony_ci } 1142498b56bSopenharmony_ci return 1; 1152498b56bSopenharmony_ci} 1162498b56bSopenharmony_ci 1172498b56bSopenharmony_civoid LogKmsg::ReadAllKmsg() 1182498b56bSopenharmony_ci{ 1192498b56bSopenharmony_ci prctl(PR_SET_NAME, "hilogd.rd_kmsg"); 1202498b56bSopenharmony_ci#ifdef __linux__ 1212498b56bSopenharmony_ci std::cout << "Platform: Linux" << std::endl; 1222498b56bSopenharmony_ci LinuxReadAllKmsg(); 1232498b56bSopenharmony_ci#endif 1242498b56bSopenharmony_ci} 1252498b56bSopenharmony_ci 1262498b56bSopenharmony_civoid LogKmsg::Start() 1272498b56bSopenharmony_ci{ 1282498b56bSopenharmony_ci std::lock_guard<decltype(startMtx)> lock(startMtx); 1292498b56bSopenharmony_ci if (threadStatus == NONEXIST || threadStatus == STOP) { 1302498b56bSopenharmony_ci logKmsgThread = std::thread ([this]() { 1312498b56bSopenharmony_ci ReadAllKmsg(); 1322498b56bSopenharmony_ci }); 1332498b56bSopenharmony_ci } else { 1342498b56bSopenharmony_ci std::cout << " Thread already started!\n"; 1352498b56bSopenharmony_ci } 1362498b56bSopenharmony_ci threadStatus = START; 1372498b56bSopenharmony_ci} 1382498b56bSopenharmony_ci 1392498b56bSopenharmony_civoid LogKmsg::Stop() 1402498b56bSopenharmony_ci{ 1412498b56bSopenharmony_ci if (threadStatus == NONEXIST || threadStatus == STOP) { 1422498b56bSopenharmony_ci std::cout << "Thread was exited or not started!\n"; 1432498b56bSopenharmony_ci return; 1442498b56bSopenharmony_ci } 1452498b56bSopenharmony_ci threadStatus = STOP; 1462498b56bSopenharmony_ci if (logKmsgThread.joinable()) { 1472498b56bSopenharmony_ci logKmsgThread.join(); 1482498b56bSopenharmony_ci } 1492498b56bSopenharmony_ci} 1502498b56bSopenharmony_ci 1512498b56bSopenharmony_ciLogKmsg::~LogKmsg() 1522498b56bSopenharmony_ci{ 1532498b56bSopenharmony_ci close(kmsgCtl); 1542498b56bSopenharmony_ci} 1552498b56bSopenharmony_ci} // namespace HiviewDFX 1562498b56bSopenharmony_ci} // namespace OHOS 157