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
40 namespace OHOS {
41 namespace HiviewDFX {
42 using namespace std;
43
44 static const string SYSTEM_BG_STUNE = "/dev/stune/system-background/cgroup.procs";
45 static const string SYSTEM_BG_CPUSET = "/dev/cpuset/system-background/cgroup.procs";
46 static const string SYSTEM_BG_BLKIO = "/dev/blkio/system-background/cgroup.procs";
47
48 #ifdef DEBUG
49 static int g_fd = -1;
50 #endif
51
SigHandler(int sig)52 static 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
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(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
main()227 int main()
228 {
229 (void)OHOS::HiviewDFX::HilogdEntry();
230 return 0;
231 }
232