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 std::cout<<"Exited!"<<std::endl;
61 }
62 }
63
WriteStringToFile(int fd,const std::string & content)64 static 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
WriteStringToFile(const std::string & content,const std::string & filePath)79 static 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
RedirectStdStreamToLogFile()108 static 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
HilogdEntry()135 int 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;
145 LogCollector logCollector(hilogBuffer);
146
147 // Start log_collector
148 #ifndef __RECV_MSG_WITH_UCRED_
149 auto onDataReceive = [&logCollector](std::vector<char>& data) {
150 logCollector.onDataRecv(data);
151 };
152 #else
153 auto onDataReceive = [&logCollector](const ucred& cred, std::vector<char>& data) {
154 logCollector.onDataRecv(cred, data);
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 auto startupCheckTask = std::async(std::launch::async, [&hilogBuffer]() {
172 prctl(PR_SET_NAME, "hilogd.pst_res");
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 hilogBuffer.InitBuffLen();
182 RestorePersistJobs(hilogBuffer);
183 }
184 });
185
186 bool kmsgEnable = IsKmsgSwitchOn();
187 if (kmsgEnable) {
188 LogKmsg& logKmsg = LogKmsg::GetInstance(hilogBuffer);
189 logKmsg.Start();
190 }
191
192 auto cgroupWriteTask = std::async(std::launch::async, [&hilogBuffer]() {
193 prctl(PR_SET_NAME, "hilogd.cgroup_set");
194 string myPid = to_string(getpid());
195 (void)WriteStringToFile(myPid, SYSTEM_BG_STUNE);
196 (void)WriteStringToFile(myPid, SYSTEM_BG_CPUSET);
197 (void)WriteStringToFile(myPid, SYSTEM_BG_BLKIO);
198 });
199
200 auto cmdExecuteTask = std::async(std::launch::async, [&logCollector, &hilogBuffer]() {
201 prctl(PR_SET_NAME, "hilogd.cmd");
202 CmdList controlCmdList {
203 IoctlCmd::PERSIST_START_RQST,
204 IoctlCmd::PERSIST_STOP_RQST,
205 IoctlCmd::PERSIST_QUERY_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, controlCmdList, ("hilogd.control"));
215 controlExecutor.MainLoop(CONTROL_SOCKET_NAME);
216 });
217
218 CmdList outputList {IoctlCmd::OUTPUT_RQST};
219 CmdExecutor outputExecutor(logCollector, hilogBuffer, outputList, ("hilogd.output"));
220 outputExecutor.MainLoop(OUTPUT_SOCKET_NAME);
221
222 return 0;
223 }
224 } // namespace HiviewDFX
225 } // namespace OHOS
226
main()227 int main()
228 {
229 (void)OHOS::HiviewDFX::HilogdEntry();
230 return 0;
231 }
232