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