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 <iostream> 17#include <sys/stat.h> 18#include <sys/prctl.h> 19#include <sys/stat.h> 20#include <future> 21#include <unistd.h> 22#include <csignal> 23#include <fcntl.h> 24#include <hilog_input_socket_server.h> 25#include <properties.h> 26#include <log_utils.h> 27 28#include "cmd_executor.h" 29#include "ffrt.h" 30#include "flow_control.h" 31#include "log_kmsg.h" 32#include "log_collector.h" 33#include "service_controller.h" 34 35#ifdef DEBUG 36#include <cstdio> 37#include <cerrno> 38#endif 39 40namespace OHOS { 41namespace HiviewDFX { 42using namespace std; 43 44static const string SYSTEM_BG_STUNE = "/dev/stune/system-background/cgroup.procs"; 45static const string SYSTEM_BG_CPUSET = "/dev/cpuset/system-background/cgroup.procs"; 46static const string SYSTEM_BG_BLKIO = "/dev/blkio/system-background/cgroup.procs"; 47 48#ifdef DEBUG 49static int g_fd = -1; 50#endif 51 52static void SigHandler(int sig) 53{ 54 if (sig == SIGINT) { 55#ifdef DEBUG 56 if (g_fd > 0) { 57 close(g_fd); 58 g_fd = -1; 59 } 60#endif 61 } 62} 63 64static bool WriteStringToFile(int fd, const std::string& content) 65{ 66 const char *p = content.data(); 67 size_t remaining = content.size(); 68 while (remaining > 0) { 69 ssize_t n = write(fd, p, remaining); 70 if (n == -1) { 71 return false; 72 } 73 p += n; 74 remaining -= static_cast<size_t>(n); 75 } 76 return true; 77} 78 79static bool WriteStringToFile(const std::string& content, const std::string& filePath) 80{ 81 int ret = WaitingToDo(WAITING_DATA_MS, filePath, [](const string &path) { 82 int fd; 83 if (!access(path.c_str(), W_OK)) { 84 fd = open(path.c_str(), O_WRONLY | O_CLOEXEC); 85 if (fd >= 0) { 86 close(fd); 87 return RET_SUCCESS; 88 } 89 } 90 return RET_FAIL; 91 }); 92 if (ret != RET_SUCCESS) { 93 return false; 94 } 95 if (access(filePath.c_str(), W_OK)) { 96 return false; 97 } 98 int fd = open(filePath.c_str(), O_WRONLY | O_CLOEXEC); 99 if (fd < 0) { 100 return false; 101 } 102 bool result = WriteStringToFile(fd, content); 103 close(fd); 104 return result; 105} 106 107#ifdef DEBUG 108static void RedirectStdStreamToLogFile() 109{ 110 int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) { 111 struct stat s; 112 if (stat(path.c_str(), &s) != -1) { 113 return RET_SUCCESS; 114 } 115 return RET_FAIL; 116 }); 117 if (ret == RET_SUCCESS) { 118 const char *path = HILOG_FILE_DIR"hilogd_debug.txt"; 119 int mask = O_WRONLY | O_APPEND | O_CREAT; 120 struct stat st; 121 if (stat(path, &st) == -1) { 122 mask |= O_CREAT; 123 } 124 int fd = open(path, mask, S_IWUSR | S_IWGRP); 125 if (fd > 0) { 126 g_fd = dup2(fd, fileno(stdout)); 127 } else { 128 std::cout << "open file error: "; 129 PrintErrorno(errno); 130 } 131 } 132} 133#endif 134 135int HilogdEntry() 136{ 137 const int hilogFileMask = 0022; 138 umask(hilogFileMask); 139 140#ifdef DEBUG 141 RedirectStdStreamToLogFile(); 142#endif 143 std::signal(SIGINT, SigHandler); 144 HilogBuffer hilogBuffer(true); 145 LogCollector logCollector(hilogBuffer); 146 147 // Start log_collector 148#ifndef __RECV_MSG_WITH_UCRED_ 149 auto onDataReceive = [&logCollector](std::vector<char>& data, int dataLen) { 150 logCollector.onDataRecv(data, dataLen); 151 }; 152#else 153 auto onDataReceive = [&logCollector](const ucred& cred, std::vector<char>& data, int dataLen) { 154 logCollector.onDataRecv(cred, data, dataLen); 155 }; 156#endif 157 158 HilogInputSocketServer incomingLogsServer(onDataReceive); 159 if (incomingLogsServer.Init() < 0) { 160#ifdef DEBUG 161 cout << "Failed to init input server socket ! "; 162 PrintErrorno(errno); 163#endif 164 } else { 165#ifdef DEBUG 166 cout << "Begin to listen !\n"; 167#endif 168 incomingLogsServer.RunServingThread(); 169 } 170 171 HilogBuffer kmsgBuffer(false); 172 ffrt::submit([&hilogBuffer, &kmsgBuffer]() { 173 int ret = WaitingToDo(WAITING_DATA_MS, HILOG_FILE_DIR, [](const string &path) { 174 struct stat s; 175 if (stat(path.c_str(), &s) != -1) { 176 return RET_SUCCESS; 177 } 178 return RET_FAIL; 179 }); 180 if (ret == RET_SUCCESS) { 181 RestorePersistJobs(hilogBuffer, kmsgBuffer); 182 } 183 }, {}, {}, ffrt::task_attr().name("hilogd.pst_res")); 184 185 bool kmsgEnable = IsKmsgSwitchOn(); 186 if (kmsgEnable) { 187 LogKmsg& logKmsg = LogKmsg::GetInstance(kmsgBuffer); 188 logKmsg.Start(); 189 } 190 191 ffrt::submit([]() { 192 string myPid = to_string(getprocpid()); 193 (void)WriteStringToFile(myPid, SYSTEM_BG_STUNE); 194 (void)WriteStringToFile(myPid, SYSTEM_BG_CPUSET); 195 (void)WriteStringToFile(myPid, SYSTEM_BG_BLKIO); 196 }, {}, {}, ffrt::task_attr().name("hilogd.cgroup_set")); 197 198 std::thread([&logCollector, &hilogBuffer, &kmsgBuffer] () { 199 prctl(PR_SET_NAME, "hilogd.cmd"); 200 CmdList controlCmdList { 201 IoctlCmd::PERSIST_START_RQST, 202 IoctlCmd::PERSIST_STOP_RQST, 203 IoctlCmd::PERSIST_QUERY_RQST, 204 IoctlCmd::PERSIST_REFRESH_RQST, 205 IoctlCmd::PERSIST_CLEAR_RQST, 206 IoctlCmd::BUFFERSIZE_GET_RQST, 207 IoctlCmd::BUFFERSIZE_SET_RQST, 208 IoctlCmd::STATS_QUERY_RQST, 209 IoctlCmd::STATS_CLEAR_RQST, 210 IoctlCmd::DOMAIN_FLOWCTRL_RQST, 211 IoctlCmd::LOG_REMOVE_RQST, 212 IoctlCmd::KMSG_ENABLE_RQST, 213 }; 214 CmdExecutor controlExecutor(logCollector, hilogBuffer, kmsgBuffer, controlCmdList, ("hilogd.control")); 215 controlExecutor.MainLoop(CONTROL_SOCKET_NAME); 216 }).detach(); 217 218 CmdList outputList {IoctlCmd::OUTPUT_RQST}; 219 CmdExecutor outputExecutor(logCollector, hilogBuffer, kmsgBuffer, outputList, ("hilogd.output")); 220 outputExecutor.MainLoop(OUTPUT_SOCKET_NAME); 221 222 return 0; 223} 224} // namespace HiviewDFX 225} // namespace OHOS 226 227int main() 228{ 229 (void)OHOS::HiviewDFX::HilogdEntry(); 230 return 0; 231} 232