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